feat: 서버 상세 모달 구매일자 필드 추가 및 특정 법인명 제거
This commit is contained in:
@@ -27,7 +27,7 @@ export function renderTable(mainContent: HTMLElement) {
|
||||
}
|
||||
|
||||
function renderHwTable(table: HTMLTableElement, container: HTMLElement, mainContent: HTMLElement) {
|
||||
const list = state.masterData.hw.filter(a => a.type === state.activeSubTab);
|
||||
const fullList = state.masterData.hw.filter(a => a.type === state.activeSubTab);
|
||||
const tableWrapper = document.createElement('div');
|
||||
tableWrapper.className = 'table-container';
|
||||
|
||||
@@ -37,8 +37,8 @@ function renderHwTable(table: HTMLTableElement, container: HTMLElement, mainCont
|
||||
container.appendChild(tableWrapper);
|
||||
mainContent.appendChild(container);
|
||||
const tbody = document.getElementById('dynamic-tbody')!;
|
||||
if (list.length === 0) { tbody.innerHTML = `<tr><td colspan="17">등록된 자산이 없습니다.</td></tr>`; return; }
|
||||
list.forEach((asset, idx) => {
|
||||
if (fullList.length === 0) { tbody.innerHTML = `<tr><td colspan="17">등록된 자산이 없습니다.</td></tr>`; return; }
|
||||
fullList.forEach((asset, idx) => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.innerHTML = `<td>${idx+1}</td><td>${asset.법인}</td><td>${asset.자산코드}</td><td>${asset.사용자||''}</td><td>${asset.위치||''}</td><td>${asset.CPU||''}</td><td>${asset.GPU||''}</td><td>${asset.RAM||''}</td><td>${asset.SSD1||'-'}</td><td>${asset.SSD2||'-'}</td><td>${asset.HDD1||'-'}</td><td>${asset.HDD2||'-'}</td><td>${asset.구매일||''}</td><td>${asset.금액||''}</td><td>${asset.납품업체||''}</td><td style="text-align:center;">${asset.품의서명 ? '<i data-lucide="paperclip" class="text-primary"></i>' : '-'}</td><td><button class="btn btn-outline btn-sm btn-edit">수정</button></td>`;
|
||||
@@ -51,42 +51,116 @@ function renderHwTable(table: HTMLTableElement, container: HTMLElement, mainCont
|
||||
container.appendChild(tableWrapper);
|
||||
mainContent.appendChild(container);
|
||||
const tbody = document.getElementById('dynamic-tbody')!;
|
||||
if (list.length === 0) { tbody.innerHTML = `<tr><td colspan="13">등록된 자산이 없습니다.</td></tr>`; return; }
|
||||
list.forEach((asset, idx) => {
|
||||
if (fullList.length === 0) { tbody.innerHTML = `<tr><td colspan="13">등록된 자산이 없습니다.</td></tr>`; return; }
|
||||
fullList.forEach((asset, idx) => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.innerHTML = `<td>${idx+1}</td><td>${asset.법인}</td><td>${asset.storage유형||''}</td><td>${asset.자산코드}</td><td>${asset.명칭}</td><td>${asset.위치||''}</td><td>${asset.모델명||''}</td><td>${asset.용량||''}</td><td>${asset.담당자_정||''}</td><td>${asset.IP주소||''}</td><td>${asset.구매일||''}</td><td>${asset.금액||''}</td><td><button class="btn btn-outline btn-sm btn-edit">수정</button></td>`;
|
||||
tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openStorageModal(asset); });
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
} 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>모델명</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>`;
|
||||
}
|
||||
} else if (state.activeSubTab === '서버') {
|
||||
// --- 서버 전용 필터 및 검색 기능 ---
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
|
||||
// 법인, 유형, 위치 고유값 추출
|
||||
const corps = Array.from(new Set(fullList.map(a => a.법인))).filter(Boolean).sort();
|
||||
const types = Array.from(new Set(fullList.map(a => a.storage유형))).filter(Boolean).sort();
|
||||
const locations = Array.from(new Set(fullList.map(a => {
|
||||
const loc = String(a.위치 || '');
|
||||
if (loc.startsWith('서관') || loc.startsWith('동관')) return 'IDC';
|
||||
return loc.split(' ')[0]; // 첫 단어 기준 (본사, 지사, 마천사무실 등)
|
||||
}))).filter(Boolean).sort();
|
||||
|
||||
filterBar.innerHTML = `
|
||||
<div class="search-item flex-1">
|
||||
<label>통합 검색 (자산번호/용도/모델명)</label>
|
||||
<input type="text" id="filter-keyword" placeholder="검색어를 입력하세요..." autocomplete="off">
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>법인</label>
|
||||
<select id="filter-corp">
|
||||
<option value="">전체 법인</option>
|
||||
${corps.map(c => `<option value="${c}">${c}</option>`).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>유형</label>
|
||||
<select id="filter-type">
|
||||
<option value="">전체 유형</option>
|
||||
${types.map(t => `<option value="${t}">${t}</option>`).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>설치위치</label>
|
||||
<select id="filter-location">
|
||||
<option value="">전체 위치</option>
|
||||
${locations.map(l => `<option value="${l}">${l}</option>`).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<button id="btn-reset-filters" class="btn btn-outline btn-reset" title="검색 조건 초기화">
|
||||
<i data-lucide="refresh-ccw" style="width:14px; height:14px;"></i> 필터 초기화
|
||||
</button>
|
||||
`;
|
||||
container.appendChild(filterBar);
|
||||
|
||||
table.innerHTML = `<thead><tr><th>No</th><th>법인</th><th>자산번호</th><th>유형</th><th>용도</th><th>상세</th><th>설치위치</th><th>담당자</th><th>모델명</th><th>OS</th><th>CPU</th><th>RAM</th><th>Storage</th></tr></thead><tbody id="dynamic-tbody"></tbody>`;
|
||||
tableWrapper.appendChild(table);
|
||||
container.appendChild(tableWrapper);
|
||||
mainContent.appendChild(container);
|
||||
const tbody = document.getElementById('dynamic-tbody')!;
|
||||
const colCount = state.activeSubTab === '서버' ? 13 : (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 tbody = document.getElementById('dynamic-tbody')!;
|
||||
|
||||
const updateTable = () => {
|
||||
const keyword = (document.getElementById('filter-keyword') as HTMLInputElement).value.toLowerCase().trim();
|
||||
const corp = (document.getElementById('filter-corp') as HTMLSelectElement).value;
|
||||
const type = (document.getElementById('filter-type') as HTMLSelectElement).value;
|
||||
const location = (document.getElementById('filter-location') as HTMLSelectElement).value;
|
||||
|
||||
const filtered = fullList.filter(asset => {
|
||||
const formatAsset = (v: any) => String(v || '').toLowerCase();
|
||||
const matchKeyword = !keyword ||
|
||||
formatAsset(asset.자산코드).includes(keyword) ||
|
||||
formatAsset(asset.용도).includes(keyword) ||
|
||||
formatAsset(asset.상세).includes(keyword) ||
|
||||
formatAsset(asset.모델명).includes(keyword) ||
|
||||
formatAsset(asset.담당자_정).includes(keyword) ||
|
||||
formatAsset(asset.담당자_부).includes(keyword);
|
||||
|
||||
const matchCorp = !corp || asset.법인 === corp;
|
||||
const matchType = !type || asset.storage유형 === type;
|
||||
|
||||
let matchLocation = true;
|
||||
if (location) {
|
||||
const loc = String(asset.위치 || '');
|
||||
if (location === 'IDC') {
|
||||
matchLocation = loc.startsWith('서관') || loc.startsWith('동관');
|
||||
} else {
|
||||
matchLocation = loc.includes(location);
|
||||
}
|
||||
}
|
||||
|
||||
return matchKeyword && matchCorp && matchType && matchLocation;
|
||||
});
|
||||
|
||||
tbody.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="13" style="text-align:center; padding: 3rem; color: var(--text-muted);">검색 결과가 없습니다.</td></tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
filtered.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>`;
|
||||
|
||||
const mainManager = asset.담당자_정 || '';
|
||||
const subManager = asset.담당자_부 || '';
|
||||
const managerHtml = [mainManager ? `${getBadge('정', '#1E5149')} ${mainManager}` : '', subManager ? `${getBadge('부', '#9CA3AF')} ${subManager}` : ''].filter(v => v !== '').join(' / ');
|
||||
const storageInfo = [asset.SSD1, asset.SSD2].filter(v => v && v !== '').join(' / ');
|
||||
|
||||
// 위치 정보 가공 (서관/동관 -> IDC)
|
||||
let locationHtml = formatInline(asset.위치);
|
||||
if (locationHtml.startsWith('서관') || locationHtml.startsWith('동관')) {
|
||||
locationHtml = `IDC(${locationHtml})`;
|
||||
@@ -108,10 +182,42 @@ function renderHwTable(table: HTMLTableElement, container: HTMLElement, mainCont
|
||||
<td class="text-nowrap">${formatInline(storageInfo)}</td>
|
||||
`;
|
||||
tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset); });
|
||||
} 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 btn-outline btn-sm btn-edit">수정</button></td>`;
|
||||
tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset); });
|
||||
}
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
createIcons({ icons: { RefreshCcw, Paperclip } });
|
||||
};
|
||||
|
||||
const keywordInput = document.getElementById('filter-keyword') as HTMLInputElement;
|
||||
const corpSelect = document.getElementById('filter-corp') as HTMLSelectElement;
|
||||
const typeSelect = document.getElementById('filter-type') as HTMLSelectElement;
|
||||
const locationSelect = document.getElementById('filter-location') as HTMLSelectElement;
|
||||
const resetBtn = document.getElementById('btn-reset-filters') as HTMLButtonElement;
|
||||
|
||||
keywordInput.addEventListener('input', updateTable);
|
||||
corpSelect.addEventListener('change', updateTable);
|
||||
typeSelect.addEventListener('change', updateTable);
|
||||
locationSelect.addEventListener('change', updateTable);
|
||||
resetBtn.addEventListener('click', () => {
|
||||
keywordInput.value = ''; corpSelect.value = ''; typeSelect.value = ''; locationSelect.value = '';
|
||||
updateTable();
|
||||
});
|
||||
|
||||
updateTable();
|
||||
} 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>`;
|
||||
tableWrapper.appendChild(table);
|
||||
container.appendChild(tableWrapper);
|
||||
mainContent.appendChild(container);
|
||||
const tbody = document.getElementById('dynamic-tbody')!;
|
||||
const colCount = state.activeSubTab === '전산비품' ? 11 : 10;
|
||||
if (fullList.length === 0) { tbody.innerHTML = `<tr><td colspan="${colCount}">등록된 자산이 없습니다.</td></tr>`; return; }
|
||||
|
||||
fullList.forEach((asset, idx) => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.style.cursor = 'pointer';
|
||||
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 btn-outline btn-sm btn-edit">수정</button></td>`;
|
||||
tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset); });
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user