Files
ITAM/index.html
2026-04-13 14:17:43 +09:00

587 lines
27 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ITAM 자산관리 ERP</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable.min.css" />
<link rel="stylesheet" href="/src/style.css" />
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script>
</head>
<body>
<div class="app-layout">
<!-- Sidebar Navigation -->
<aside class="sidebar">
<div class="sidebar-header">
<h1>HM <span>ITAM</span></h1>
</div>
<div class="nav-section">
<h3><i data-lucide="cpu"></i> 하드웨어</h3>
<ul id="nav-hw" class="nav-list">
<li class="active" data-category="hw" data-tab="대시보드"><i data-lucide="layout-dashboard"></i> 대시보드</li>
<li data-category="hw" data-tab="개인PC"><i data-lucide="monitor"></i> 개인PC</li>
<li data-category="hw" data-tab="서버"><i data-lucide="server"></i> 서버</li>
<li data-category="hw" data-tab="스토리지"><i data-lucide="database"></i> 스토리지</li>
<li data-category="hw" data-tab="전산비품"><i data-lucide="laptop"></i> 전산비품</li>
</ul>
</div>
<div class="nav-section">
<h3><i data-lucide="layers"></i> 소프트웨어</h3>
<ul id="nav-sw" class="nav-list">
<li data-category="sw" data-tab="대시보드"><i data-lucide="layout-dashboard"></i> 대시보드</li>
<li data-category="sw" data-tab="구독SW"><i data-lucide="calendar-clock"></i> 구독 소프트웨어</li>
<li data-category="sw" data-tab="영구SW"><i data-lucide="key"></i> 영구 소프트웨어</li>
</ul>
</div>
</aside>
<!-- Main Content Area -->
<div class="main-wrapper">
<header class="top-header">
<div class="header-title">
<h2 id="current-tab-title">하드웨어 / 대시보드</h2>
</div>
<div class="header-actions">
<!-- 엑셀 컨트롤러 묶음 -->
<button id="btn-download-template" class="btn btn-outline" title="초기 데이터 입력을 위한 전체 엑셀 템플릿 다운로드">
<i data-lucide="download"></i> 통합 양식 다운로드
</button>
<label for="excel-upload" class="btn btn-outline" title="작성된 엑셀 파일 일괄 업로드">
<i data-lucide="upload"></i> 엑셀 업로드
</label>
<input type="file" id="excel-upload" accept=".xlsx, .xls" style="display: none;" />
<button id="btn-export-excel" class="btn btn-primary" title="마스터 데이터 전체를 엑셀로 저장">
<i data-lucide="file-spreadsheet"></i> 일괄 엑셀 저장
</button>
<button id="btn-add-asset" class="btn btn-primary hidden">
<i data-lucide="plus"></i> 자산 추가
</button>
</div>
</header>
<main class="content-area" id="main-content">
<!-- 대시보드 뷰, 또는 데이터 테이블 뷰가 JavaScript로 주입됩니다 -->
</main>
</div>
</div>
<!-- HW Asset Modal -->
<div id="hw-asset-modal" class="modal-overlay hidden">
<div class="modal-content">
<div class="modal-header">
<h2 id="hw-modal-title">자산 상세 정보</h2>
<button id="btn-close-hw-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<form id="hw-asset-form" class="grid-form">
<input type="hidden" id="hw-asset-id" />
<input type="hidden" id="hw-asset-type" /> <!-- 개인PC, 서버 등 저장용 -->
<div class="form-group">
<label for="hw-법인">법인</label>
<input type="text" id="hw-법인" required />
</div>
<div class="form-group" id="hw-비품유형-group" style="display:none;">
<label for="hw-비품유형">비품유형</label>
<select id="hw-비품유형" class="form-control" style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px;">
<option value="노트북">노트북</option>
<option value="태블릿">태블릿</option>
<option value="휴대폰">휴대폰</option>
</select>
</div>
<div class="form-group">
<label for="hw-자산코드">자산코드</label>
<input type="text" id="hw-자산코드" required />
</div>
<div class="form-group">
<label for="hw-명칭">명칭</label>
<input type="text" id="hw-명칭" required />
</div>
<div class="form-group">
<label for="hw-위치">위치</label>
<input type="text" id="hw-위치" />
</div>
<div class="form-group">
<label for="hw-관리자">관리자</label>
<input type="text" id="hw-관리자" />
</div>
<div class="form-group">
<label for="hw-IP주소">IP주소</label>
<input type="text" id="hw-IP주소" />
</div>
<div class="form-group">
<label for="hw-MACaddress">MAC address</label>
<input type="text" id="hw-MACaddress" />
</div>
<div class="form-group">
<label for="hw-OS">OS</label>
<input type="text" id="hw-OS" />
</div>
<div class="form-group full-width">
<label for="hw-HW사양">H/W 사양</label>
<textarea id="hw-HW사양" rows="2"></textarea>
</div>
<div class="form-group">
<label for="hw-구매일">구매일</label>
<input type="text" id="hw-구매일" placeholder="ex) 2024-01-01" />
</div>
<div class="form-group">
<label for="hw-금액">금액</label>
<input type="text" id="hw-금액" placeholder="ex) 1,000,000" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')" />
</div>
<div class="form-group">
<label for="hw-납품업체">납품업체</label>
<input type="text" id="hw-납품업체" />
</div>
<div class="form-group full-width">
<label style="font-size:0.875rem;">품의서 (파일)</label>
<div style="display:flex; align-items:center; gap:0.5rem;">
<input type="file" id="hw-품의서" style="font-size:0.875rem;" />
<span id="hw-품의서명" style="font-size:0.75rem; color:var(--text-light)"></span>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button id="btn-delete-hw-asset" class="btn btn-outline btn-danger">삭제</button>
<div class="footer-actions">
<button id="btn-cancel-hw-modal" class="btn btn-outline">취소</button>
<button id="btn-save-hw-asset" class="btn btn-primary">저장</button>
</div>
</div>
</div>
</div>
<!-- PC Asset Modal -->
<div id="pc-asset-modal" class="modal-overlay hidden">
<div class="modal-content">
<div class="modal-header">
<h2 id="pc-modal-title">개인PC 상세 정보</h2>
<button id="btn-close-pc-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<form id="pc-asset-form" class="grid-form">
<input type="hidden" id="pc-asset-id" />
<input type="hidden" id="pc-asset-type" value="개인PC" />
<div class="form-group">
<label for="pc-법인">법인</label>
<select id="pc-법인" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
<option value="한맥">한맥 (HM)</option>
<option value="삼안">삼안 (SM)</option>
<option value="바론">바론 (BR)</option>
</select>
</div>
<div class="form-group">
<label for="pc-자산코드">자산코드</label>
<input type="text" id="pc-자산코드" placeholder="ex) HM-PC-2018-001" required />
</div>
<div class="form-group">
<label for="pc-사용자">사용자</label>
<input type="text" id="pc-사용자" required />
</div>
<div class="form-group">
<label for="pc-위치">위치</label>
<input type="text" id="pc-위치" />
</div>
<div class="form-group">
<label for="pc-CPU">CPU</label>
<input type="text" id="pc-CPU" />
</div>
<div class="form-group">
<label for="pc-GPU">GPU</label>
<input type="text" id="pc-GPU" />
</div>
<div class="form-group">
<label for="pc-RAM">RAM</label>
<input type="text" id="pc-RAM" />
</div>
<div class="form-group">
<label for="pc-SSD1">SSD1</label>
<input type="text" id="pc-SSD1" />
</div>
<div class="form-group">
<label for="pc-SSD2">SSD2</label>
<input type="text" id="pc-SSD2" />
</div>
<div class="form-group">
<label for="pc-HDD1">HDD1</label>
<input type="text" id="pc-HDD1" />
</div>
<div class="form-group">
<label for="pc-HDD2">HDD2</label>
<input type="text" id="pc-HDD2" />
</div>
<div class="form-group">
<label for="pc-구매일">구매일</label>
<input type="text" id="pc-구매일" placeholder="ex) 2024-01-01" />
</div>
<div class="form-group">
<label for="pc-금액">금액</label>
<input type="text" id="pc-금액" placeholder="ex) 1,000,000" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')" />
</div>
<div class="form-group">
<label for="pc-납품업체">납품업체</label>
<input type="text" id="pc-납품업체" />
</div>
<div class="form-group full-width">
<label style="font-size:0.875rem;">품의서 (파일)</label>
<div style="display:flex; align-items:center; gap:0.5rem;">
<input type="file" id="pc-품의서" style="font-size:0.875rem;" />
<span id="pc-품의서명" style="font-size:0.75rem; color:var(--text-light)"></span>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button id="btn-delete-pc-asset" class="btn btn-outline btn-danger">삭제</button>
<div class="footer-actions">
<button id="btn-cancel-pc-modal" class="btn btn-outline">취소</button>
<button id="btn-save-pc-asset" class="btn btn-primary">저장</button>
</div>
</div>
</div>
</div>
<!-- Storage Asset Modal -->
<div id="storage-asset-modal" class="modal-overlay hidden">
<div class="modal-content">
<div class="modal-header">
<h2 id="storage-modal-title">스토리지 상세 정보</h2>
<button id="btn-close-storage-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<form id="storage-asset-form" class="grid-form">
<input type="hidden" id="storage-asset-id" />
<input type="hidden" id="storage-asset-type" value="스토리지" />
<div class="form-group">
<label for="storage-법인">법인</label>
<select id="storage-법인" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
<option value="한맥">한맥 (HM)</option>
<option value="삼안">삼안 (SM)</option>
<option value="바론">바론 (BR)</option>
</select>
</div>
<div class="form-group">
<label for="storage-유형">유형</label>
<select id="storage-유형" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
<option value="NAS">NAS</option>
<option value="DAS">DAS</option>
</select>
</div>
<div class="form-group">
<label for="storage-자산코드">자산코드</label>
<input type="text" id="storage-자산코드" placeholder="ex) HM-NAS-2024-001" required />
</div>
<div class="form-group">
<label for="storage-명칭">명칭</label>
<input type="text" id="storage-명칭" required />
</div>
<div class="form-group">
<label for="storage-위치">위치</label>
<input type="text" id="storage-위치" />
</div>
<div class="form-group">
<label for="storage-모델명">모델명</label>
<input type="text" id="storage-모델명" />
</div>
<div class="form-group">
<label for="storage-용량">용량</label>
<input type="text" id="storage-용량" />
</div>
<div class="form-group">
<label for="storage-담당자_정">담당자(정)</label>
<input type="text" id="storage-담당자_정" />
</div>
<div class="form-group">
<label for="storage-담당자_부">담당자(부)</label>
<input type="text" id="storage-담당자_부" />
</div>
<div class="form-group">
<label for="storage-IP주소">IP주소</label>
<input type="text" id="storage-IP주소" />
</div>
<div class="form-group">
<label for="storage-MAC주소">MAC 주소</label>
<input type="text" id="storage-MAC주소" />
</div>
<div class="form-group">
<label for="storage-구매일">구매일</label>
<input type="text" id="storage-구매일" placeholder="ex) 2024-01-01" />
</div>
<div class="form-group">
<label for="storage-금액">금액</label>
<input type="text" id="storage-금액" placeholder="ex) 1,000,000" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')" />
</div>
<div class="form-group">
<label for="storage-납품업체">납품업체</label>
<input type="text" id="storage-납품업체" />
</div>
<div class="form-group full-width">
<label style="font-size:0.875rem;">품의서 (파일)</label>
<div style="display:flex; align-items:center; gap:0.5rem;">
<input type="file" id="storage-품의서" style="font-size:0.875rem;" />
<span id="storage-품의서명" style="font-size:0.75rem; color:var(--text-light)"></span>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button id="btn-delete-storage-asset" class="btn btn-outline btn-danger">삭제</button>
<div class="footer-actions">
<button id="btn-cancel-storage-modal" class="btn btn-outline">취소</button>
<button id="btn-save-storage-asset" class="btn btn-primary">저장</button>
</div>
</div>
</div>
</div>
<!-- SW Asset Modal -->
<div id="sw-asset-modal" class="modal-overlay hidden">
<div class="modal-content">
<div class="modal-header">
<h2 id="sw-modal-title">S/W 상세 정보</h2>
<button id="btn-close-sw-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<form id="sw-asset-form" class="grid-form">
<input type="hidden" id="sw-asset-id" />
<input type="hidden" id="sw-asset-type" />
<div class="form-group">
<label for="sw-법인">법인</label>
<select id="sw-법인" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
<option value="한맥">한맥 (HM)</option>
<option value="삼안">삼안 (SM)</option>
<option value="바론">바론 (BR)</option>
</select>
</div>
<div class="form-group">
<label for="sw-제품명">제품명</label>
<input type="text" id="sw-제품명" required />
</div>
<div class="form-group">
<label for="sw-구매일">구매일</label>
<input type="text" id="sw-구매일" placeholder="ex) 2024-01-01" />
</div>
<div class="form-group" id="sw-구독일-group">
<label for="sw-구독일">구독일(시작~끝)</label>
<input type="text" id="sw-구독일" placeholder="ex) 2024-01-01 ~ 2024-12-31" />
</div>
<div class="form-group" id="sw-유지보수-group" style="display:none;">
<label for="sw-유지보수여부">유지보수 여부</label>
<label style="display:flex; align-items:center; gap:0.5rem; height: 38px;">
<input type="checkbox" id="sw-유지보수여부" /> 대상 여부
</label>
</div>
<div class="form-group">
<label for="sw-금액">금액</label>
<input type="text" id="sw-금액" placeholder="ex) 1,000,000" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')" />
</div>
<div class="form-group">
<label for="sw-수량">수량 (보유량)</label>
<input type="number" id="sw-수량" min="1" value="1" style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;" />
</div>
<div class="form-group">
<label for="sw-계정명">계정명</label>
<input type="text" id="sw-계정명" />
</div>
<div class="form-group">
<label for="sw-납품업체">납품업체</label>
<input type="text" id="sw-납품업체" />
</div>
<div class="form-group">
<label for="sw-비고">비고</label>
<input type="text" id="sw-비고" />
</div>
</form>
</div>
<div class="modal-footer">
<button id="btn-delete-sw-asset" class="btn btn-outline btn-danger">삭제</button>
<div class="footer-actions">
<button id="btn-cancel-sw-modal" class="btn btn-outline">취소</button>
<button id="btn-save-sw-asset" class="btn btn-primary">저장</button>
</div>
</div>
</div>
</div>
<!-- SW User Management Modal -->
<div id="sw-user-modal" class="modal-overlay hidden">
<div class="modal-content" style="max-width: 600px;">
<div class="modal-header">
<h2 id="sw-user-modal-title">S/W 할당 사용자 목록</h2>
<button id="btn-close-sw-user-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<input type="hidden" id="sw-user-asset-id" />
<div style="text-align: right; margin-bottom: 0.5rem;">
<button type="button" id="btn-open-add-user" class="btn btn-primary" style="padding: 0.25rem 1rem;"><i data-lucide="plus"></i> 새 사용자 추가</button>
</div>
<div class="table-container" style="max-height: 250px; overflow-y: auto; border: 1px solid #e2e8f0; border-radius: 4px; margin-top:0;">
<table style="width:100%; border-collapse: collapse; font-size:0.875rem;">
<thead style="position: sticky; top: 0; background: var(--bg-light); z-index: 10;">
<tr style="border-bottom: 1px solid var(--border);">
<th style="padding:0.5rem; text-align:left;">법인</th>
<th style="padding:0.5rem; text-align:left;">부서/팀</th>
<th style="padding:0.5rem; text-align:left;">직위</th>
<th style="padding:0.5rem; text-align:left;">이름</th>
<th style="padding:0.5rem; text-align:center;">사용기간</th>
<th style="padding:0.5rem; text-align:center;">첨부파일</th>
<th style="padding:0.5rem; text-align:center;">관리</th>
</tr>
</thead>
<tbody id="user-list-body">
<!-- Users will be injected here -->
</tbody>
</table>
</div>
</div>
<div class="modal-footer" style="justify-content: flex-end;">
<div class="footer-actions">
<button id="btn-cancel-sw-user-modal" class="btn btn-outline">닫기</button>
<button id="btn-save-sw-user-mapping" class="btn btn-primary">변경사항 저장</button>
</div>
</div>
</div>
</div>
<!-- SW User Form Modal (Add / Edit) -->
<div id="sw-user-edit-modal" class="modal-overlay hidden" style="z-index: 1100;">
<div class="modal-content" style="max-width: 500px;">
<div class="modal-header">
<h2 id="sw-user-edit-modal-title">사용자 추가</h2>
<button id="btn-close-sw-user-edit-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<input type="hidden" id="edit-user-idx" value="-1" />
<div style="display:grid; grid-template-columns: 1fr 1fr; gap:0.5rem;">
<div class="form-group">
<label for="new-user-법인" style="font-size:0.875rem;">법인</label>
<select id="new-user-법인" class="form-control" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;">
<option value="한맥">한맥</option><option value="삼안">삼안</option><option value="바론">바론</option>
</select>
</div>
<div class="form-group">
<label for="new-user-부서" style="font-size:0.875rem;">부서</label>
<input type="text" id="new-user-부서" placeholder="ex: 기술부" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" />
</div>
<div class="form-group">
<label for="new-user-팀" style="font-size:0.875rem;"></label>
<input type="text" id="new-user-팀" placeholder="ex: 개발1팀" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" />
</div>
<div class="form-group">
<label for="new-user-직위" style="font-size:0.875rem;">직위</label>
<input type="text" id="new-user-직위" placeholder="ex: 대리" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" />
</div>
<div class="form-group" style="grid-column: span 2;">
<label for="new-user-이름" style="font-size:0.875rem;">이름 <span style="color:var(--danger)">*</span></label>
<input type="text" id="new-user-이름" placeholder="ex: 홍길동" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" required />
</div>
<div class="form-group" style="grid-column: span 2;">
<label for="new-user-사용기간" style="font-size:0.875rem;">사용기간</label>
<input type="text" id="new-user-사용기간" placeholder="ex: 2024.01~12" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" />
</div>
<div class="form-group" style="grid-column: span 2;">
<label style="font-size:0.875rem;">신청서 (파일)</label>
<div style="display:flex; align-items:center; gap:0.5rem;">
<input type="file" id="new-user-신청서" style="font-size:0.875rem;" />
<span id="new-user-신청서명" style="font-size:0.75rem; color:var(--text-light)"></span>
</div>
</div>
</div>
</div>
<div class="modal-footer" style="justify-content: flex-end;">
<div class="footer-actions">
<button id="btn-cancel-sw-user-edit" class="btn btn-outline">취소</button>
<button id="btn-save-edit-user" class="btn btn-primary">확인</button>
</div>
</div>
</div>
</div>
<!-- Dashboard Detail Modal -->
<div id="dashboard-detail-modal" class="modal-overlay hidden" style="z-index: 1200;">
<div class="modal-content" style="max-width: 1000px; max-height: 80vh; display: flex; flex-direction: column;">
<div class="modal-header">
<h2 id="dashboard-detail-modal-title">상세 자산 목록</h2>
<button id="btn-close-dashboard-detail" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
</div>
<div class="modal-body" style="overflow-y: auto; flex: 1; padding: 0;">
<div class="table-container" style="box-shadow: none; border-radius: 0;">
<table style="width: 100%;">
<thead>
<tr>
<th>No</th><th>유형</th><th>자산코드</th><th>명칭/모델</th>
<th>위치</th><th>담당/사용자</th><th>구매일</th><th>금액</th>
</tr>
</thead>
<tbody id="dashboard-detail-tbody">
</tbody>
</table>
</div>
</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>