refactor: standardize modal system, unify hardware DB schemas, and implement automatic asset reclassification

This commit is contained in:
2026-04-20 17:56:19 +09:00
parent 5372cda59f
commit 5248b494e9
24 changed files with 5453 additions and 1318 deletions

View File

@@ -1,6 +1,17 @@
import { state } from '../../core/state';
import { HardwareAsset } from '../../core/excelHandler';
import { state, saveHardwareAsset, deleteHardwareAsset } from '../../core/state';
import { HardwareAsset, MasterAssetData } from '../../core/excelHandler';
import { openModal, closeModals } from './BaseModal';
import { createIcons, Paperclip } from 'lucide';
import { CORP_LIST, ORG_LIST, HW_TYPE_LIST, LOCATION_DATA, TYPE_PREFIX_MAP } from './SharedData';
import {
generateOptionsHTML,
setFieldValue,
getFieldValue,
parseAndSetLocation,
bindLocationEvents,
getCombinedLocation,
setEditLock
} from './ModalUtils';
let currentAsset: HardwareAsset | null = null;
let isEditMode = false;
@@ -17,15 +28,38 @@ const HW_MODAL_HTML = `
<input type="hidden" id="hw-asset-id" />
<input type="hidden" id="hw-asset-type" />
<!-- Group 1: 기본 정보 -->
<!-- Group 1: 기본 정보 (Identity) -->
<div class="form-section-title">기본 정보 (Identity)</div>
<div class="form-group">
<label for="hw-법인">법인</label>
<input type="text" id="hw-법인" required />
<label for="hw-법인">구매법인</label>
<select id="hw-법인" required>${generateOptionsHTML(CORP_LIST)}</select>
</div>
<div class="form-group">
<label for="hw-자산코드">자산번호/코드</label>
<input type="text" id="hw-자산코드" required />
<div style="display:flex; gap:0.5rem;">
<input type="text" id="hw-자산코드" readonly placeholder="번호 생성을 클릭하세요" required />
<button type="button" id="btn-generate-hw-code" class="btn btn-outline" style="white-space:nowrap; padding:0 10px; font-size:0.8rem;">번호 생성</button>
</div>
</div>
<div class="form-group">
<label for="hw-현사용조직">현 사용조직</label>
<select id="hw-현사용조직">${generateOptionsHTML(ORG_LIST)}</select>
</div>
<div class="form-group" id="hw-이전사용조직-group">
<label for="hw-이전사용조직">이전 사용조직</label>
<input type="text" id="hw-이전사용조직" readonly />
</div>
<div class="form-group" id="hw-유형-group">
<label for="hw-유형">유형</label>
<select id="hw-유형">${generateOptionsHTML(HW_TYPE_LIST)}</select>
</div>
<div class="form-group" id="hw-상세용도-group" style="display:none;">
<label for="hw-상세용도">상세용도</label>
<select id="hw-상세용도">
<option value="">선택</option>
<option value="서버">서버</option>
<option value="개인PC">개인PC</option>
</select>
</div>
<div class="form-group server-only">
<label for="hw-용도">용도</label>
@@ -35,7 +69,7 @@ const HW_MODAL_HTML = `
<label for="hw-상세">상세 내용</label>
<input type="text" id="hw-상세" />
</div>
<div class="form-group non-server">
<div class="form-group non-server" id="hw-명칭-group">
<label for="hw-명칭">명칭</label>
<input type="text" id="hw-명칭" />
</div>
@@ -44,79 +78,83 @@ const HW_MODAL_HTML = `
<input type="text" id="hw-비고" />
</div>
<!-- Group 2: 네트워크 정보 -->
<div class="form-section-title server-only">네트워크 정보 (Connectivity)</div>
<div class="form-group server-only">
<!-- Group 2: 네트워크 정보 (Connectivity) -->
<div class="form-section-title server-only" id="hw-network-title">네트워크 정보 (Connectivity)</div>
<div class="form-group server-only" id="hw-ip-group">
<label for="hw-IP주소">IP 주소 1</label>
<input type="text" id="hw-IP주소" />
</div>
<div class="form-group server-only">
<div class="form-group server-only" id="hw-ip2-group">
<label for="hw-IP2">IP 주소 2</label>
<input type="text" id="hw-IP2" />
</div>
<div class="form-group server-only">
<div class="form-group server-only" id="hw-remote-group">
<label for="hw-원격접속">원격 도구 (Anydesk/Chrome 등)</label>
<input type="text" id="hw-원격접속" />
</div>
<div class="form-group server-only">
<div class="form-group server-only" id="hw-server-id-group">
<label for="hw-서버ID">서버 ID</label>
<input type="text" id="hw-서버ID" />
</div>
<div class="form-group server-only">
<div class="form-group server-only" id="hw-server-pw-group">
<label for="hw-서버PW">서버 PW</label>
<input type="text" id="hw-서버PW" />
</div>
<div class="form-group non-server" id="hw-IP주소-group">
<div class="form-group non-server" id="hw-ip-non-server-group">
<label for="hw-IP주소-non-server">IP 주소</label>
<input type="text" id="hw-IP주소-non-server" />
</div>
<!-- Group 3: 시스템 사양 -->
<div class="form-section-title">시스템 사양 (Specifications)</div>
<div class="form-group">
<!-- Group 3: 시스템 사양 (Specifications) -->
<div class="form-section-title" id="hw-spec-title">시스템 사양 (Specifications)</div>
<div class="form-group" id="hw-model-group">
<label for="hw-모델명">모델명</label>
<input type="text" id="hw-모델명" />
</div>
<div class="form-group">
<div class="form-group" id="hw-os-group">
<label for="hw-OS">운영체제 (OS)</label>
<input type="text" id="hw-OS" />
</div>
<div class="form-group">
<div class="form-group" id="hw-cpu-group">
<label for="hw-CPU">CPU 사양</label>
<input type="text" id="hw-CPU" />
</div>
<div class="form-group">
<div class="form-group" id="hw-ram-group">
<label for="hw-RAM">RAM 용량</label>
<input type="text" id="hw-RAM" />
</div>
<div class="form-group">
<div class="form-group" id="hw-ssd1-group">
<label for="hw-SSD1">Storage 1 (SSD/HDD)</label>
<input type="text" id="hw-SSD1" />
</div>
<div class="form-group">
<div class="form-group" id="hw-ssd2-group">
<label for="hw-SSD2">Storage 2 (SSD/HDD)</label>
<input type="text" id="hw-SSD2" />
</div>
<div class="form-group server-only">
<div class="form-group server-only" id="hw-monitoring-group">
<label for="hw-모니터링">모니터링 여부</label>
<input type="text" id="hw-모니터링" />
</div>
<div class="form-group" id="hw-비품유형-group" style="display:none;">
<label for="hw-비품유형">비품유형</label>
<select id="hw-비품유형">
<option value="노트북">노트북</option><option value="태블릿">태블릿</option><option value="휴대폰">휴대폰</option>
</select>
</div>
<div class="form-group full-width non-server">
<div class="form-group full-width non-server" id="hw-hwspec-group">
<label for="hw-HW사양">H/W 사양 상세</label>
<textarea id="hw-HW사양" rows="2"></textarea>
</div>
<!-- Group 4: 관리 및 운영 -->
<div class="form-section-title">관리 및 운영 (Operation)</div>
<div class="form-group">
<label for="hw-위치">설치위치</label>
<input type="text" id="hw-위치" />
<!-- Group 4: 관리 및 운영 (Operation) -->
<div class="form-section-title" id="hw-op-title">관리 및 운영 (Operation)</div>
<div class="form-group hw-location-field">
<label for="hw-위치-빌딩">설치위치 (건물)</label>
<select id="hw-위치-빌딩">${generateOptionsHTML(Object.keys(LOCATION_DATA))}</select>
</div>
<div class="form-group hw-location-field">
<label for="hw-위치-상세">상세 위치</label>
<select id="hw-위치-상세">
<option value="">건물을 먼저 선택하세요</option>
</select>
</div>
<div class="form-group" id="hw-위치-기타-group" style="display:none;">
<label for="hw-위치-기타">직접 입력 (기타)</label>
<input type="text" id="hw-위치-기타" placeholder="상세 위치를 입력하세요" />
</div>
<div class="form-group">
<label for="hw-담당자_정">담당자 (정)</label>
@@ -126,13 +164,13 @@ const HW_MODAL_HTML = `
<label for="hw-담당자_부">담당자 (부)</label>
<input type="text" id="hw-담당자_부" />
</div>
<div class="form-group non-server">
<div class="form-group non-server" id="hw-purchase-date-group">
<label for="hw-구매일">구매일</label>
<input type="text" id="hw-구매일" />
</div>
<div class="form-group non-server">
<div class="form-group non-server" id="hw-price-group">
<label for="hw-금액">금액</label>
<input type="text" id="hw-금액" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\d))/g, ',')" />
<input type="text" id="hw-금액" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\\\B(?=(\\\\d{3})+(?!\d))/g, ',')" />
</div>
<div class="form-group full-width">
<label>품의서 (파일 증빙)</label>
@@ -155,181 +193,275 @@ const HW_MODAL_HTML = `
</div>
`;
export function openHwModal(asset: HardwareAsset) {
export function openHwModal(asset: HardwareAsset, mode: 'view' | 'add' = 'view') {
currentAsset = asset;
isEditMode = false;
const modal = document.getElementById('hw-asset-modal')!;
const form = document.getElementById('hw-asset-form') as HTMLFormElement;
const saveBtn = document.getElementById('btn-save-hw-asset')!;
const revertBtn = document.getElementById('btn-revert-hw-edit')!;
form.reset();
form.classList.remove('is-edit-mode');
form.classList.add('is-view-mode');
saveBtn.textContent = '수정';
revertBtn.classList.add('hidden');
// 1. 잠금 상태 통합 제어 (데이터 유무가 아닌 호출 mode에만 의존)
setEditLock('hw-asset-form', mode, {
saveBtnId: 'btn-save-hw-asset',
revertBtnId: 'btn-revert-hw-edit',
generateBtnId: 'btn-generate-hw-code'
});
isEditMode = (mode === 'add');
// 2. 데이터 바인딩
fillHwFormData(asset);
modal.classList.remove('hidden');
applyTypeSpecificUI(asset.type);
createIcons({ icons: { Paperclip } });
}
function fillHwFormData(asset: HardwareAsset) {
(document.getElementById('hw-asset-id') as HTMLInputElement).value = asset.id;
(document.getElementById('hw-asset-type') as HTMLInputElement).value = asset.type;
(document.getElementById('hw-법인') as HTMLInputElement).value = asset.;
(document.getElementById('hw-자산코드') as HTMLInputElement).value = asset.;
(document.getElementById('hw-위치') as HTMLInputElement).value = asset.;
(document.getElementById('hw-모델명') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-OS') as HTMLInputElement).value = asset.OS || '';
(document.getElementById('hw-CPU') as HTMLInputElement).value = asset.CPU || '';
(document.getElementById('hw-RAM') as HTMLInputElement).value = asset.RAM || '';
(document.getElementById('hw-SSD1') as HTMLInputElement).value = asset.SSD1 || '';
(document.getElementById('hw-SSD2') as HTMLInputElement).value = asset.SSD2 || '';
(document.getElementById('hw-담당자_정') as HTMLInputElement).value = asset._정 || asset. || '';
(document.getElementById('hw-담당자_부') as HTMLInputElement).value = asset._부 || '';
(document.getElementById('hw-품의서명') as HTMLElement).textContent = asset. || '';
function applyTypeSpecificUI(type: string) {
const detailPurpose = getFieldValue('hw-상세용도');
const form = document.getElementById('hw-asset-form') as HTMLFormElement;
if (!form) return;
const serverOnly = document.querySelectorAll('.server-only');
const nonServer = document.querySelectorAll('.non-server');
const equipGroup = document.getElementById('hw-비품유형-group')!;
const locationFields = document.querySelectorAll('.hw-location-field');
const groups: Record<string, HTMLElement | null> = {
detailPurpose: document.getElementById('hw-상세용도-group'),
model: document.getElementById('hw-model-group'),
ip: document.getElementById('hw-ip-group'),
ip2: document.getElementById('hw-ip2-group'),
remote: document.getElementById('hw-remote-group'),
os: document.getElementById('hw-os-group'),
cpu: document.getElementById('hw-cpu-group'),
ram: document.getElementById('hw-ram-group'),
ssd1: document.getElementById('hw-ssd1-group'),
ssd2: document.getElementById('hw-ssd2-group'),
monitoring: document.getElementById('hw-monitoring-group'),
serverId: document.getElementById('hw-server-id-group'),
serverPw: document.getElementById('hw-server-pw-group'),
hwSpec: document.getElementById('hw-hwspec-group'),
ipNonServer: document.getElementById('hw-ip-non-server-group'),
type: document.getElementById('hw-유형-group'),
networkTitle: document.getElementById('hw-network-title'),
specTitle: document.getElementById('hw-spec-title'),
opTitle: document.getElementById('hw-op-title')
};
if (asset.type === '서버') {
// 1. 초기화 (모든 유동 섹션 숨김)
serverOnly.forEach(el => (el as HTMLElement).style.display = 'none');
nonServer.forEach(el => (el as HTMLElement).style.display = 'none');
locationFields.forEach(el => (el as HTMLElement).style.display = 'none');
Object.values(groups).forEach(g => { if (g) g.style.display = 'none'; });
if (groups.type) groups.type.style.display = 'flex';
if (groups.opTitle) groups.opTitle.style.display = 'flex';
// 2. 유형별 정밀 규칙 적용 (사용자 정의 100% 일치)
if (type === '서버') {
serverOnly.forEach(el => (el as HTMLElement).style.display = 'flex');
nonServer.forEach(el => (el as HTMLElement).style.display = 'none');
equipGroup.style.display = 'none';
(document.getElementById('hw-용도') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-상세') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-비고') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-구매일') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-IP주소') as HTMLInputElement).value = asset.IP주소 || '';
(document.getElementById('hw-IP2') as HTMLInputElement).value = (asset as any).IP2 || '';
(document.getElementById('hw-원격접속') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-서버ID') as HTMLInputElement).value = (asset as any).ID || '';
(document.getElementById('hw-서버PW') as HTMLInputElement).value = (asset as any).PW || '';
(document.getElementById('hw-모니터링') as HTMLInputElement).value = asset. || '';
} else {
serverOnly.forEach(el => (el as HTMLElement).style.display = 'none');
locationFields.forEach(el => (el as HTMLElement).style.display = 'flex');
Object.values(groups).forEach(g => { if (g) g.style.display = 'flex'; });
}
else if (['스토리지', 'NAS', 'DAS'].includes(type)) {
serverOnly.forEach(el => (el as HTMLElement).style.display = 'flex');
locationFields.forEach(el => (el as HTMLElement).style.display = 'flex');
if (groups.networkTitle) groups.networkTitle.style.display = 'flex';
if (groups.ip) groups.ip.style.display = 'flex';
if (groups.specTitle) groups.specTitle.style.display = 'flex';
if (groups.model) groups.model.style.display = 'flex';
if (groups.ssd1) groups.ssd1.style.display = 'flex';
if (groups.ssd2) groups.ssd2.style.display = 'flex';
}
else if (type === 'PC' || type === '노트북') {
if (type === 'PC' && groups.detailPurpose) groups.detailPurpose.style.display = 'flex';
nonServer.forEach(el => (el as HTMLElement).style.display = 'flex');
(document.getElementById('hw-명칭') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-구매일') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-금액') as HTMLInputElement).value = asset. || '';
(document.getElementById('hw-HW사양') as HTMLTextAreaElement).value = asset.HW사양 || '';
(document.getElementById('hw-IP주소-non-server') as HTMLInputElement).value = asset.IP주소 || '';
if (asset.type === '전산비품') {
equipGroup.style.display = 'flex';
(document.getElementById('hw-비품유형') as HTMLSelectElement).value = asset. || '노트북';
} else {
equipGroup.style.display = 'none';
if (groups.specTitle) groups.specTitle.style.display = 'flex';
['model', 'os', 'cpu', 'ram', 'ssd1', 'ssd2', 'hwSpec', 'ipNonServer'].forEach(k => {
if (groups[k]) groups[k]!.style.display = 'flex';
});
if (type === 'PC' && detailPurpose === '서버') {
locationFields.forEach(el => (el as HTMLElement).style.display = 'flex');
if (groups.networkTitle) groups.networkTitle.style.display = 'flex';
['ip', 'ip2', 'remote', 'serverId', 'serverPw', 'monitoring'].forEach(k => {
if (groups[k]) groups[k]!.style.display = 'flex';
});
if (groups.ipNonServer) groups.ipNonServer.style.display = 'none';
}
}
else if (['CPU', 'GPU', '모바일'].includes(type)) {
if (groups.specTitle) groups.specTitle.style.display = 'flex';
if (groups.model) groups.model.style.display = 'flex';
}
else if (type === 'RAM') {
if (groups.specTitle) groups.specTitle.style.display = 'flex';
if (groups.ram) groups.ram.style.display = 'flex';
}
else if (type === 'HDD') {
if (groups.specTitle) groups.specTitle.style.display = 'flex';
if (groups.ssd1) groups.ssd1.style.display = 'flex';
}
else if (type === '태블릿') {
if (groups.specTitle) groups.specTitle.style.display = 'flex';
if (groups.model) groups.model.style.display = 'flex';
if (groups.ssd1) groups.ssd1.style.display = 'flex';
}
}
function fillHwFormData(asset: HardwareAsset) {
setFieldValue('hw-asset-id', asset.id);
setFieldValue('hw-asset-type', asset.type);
setFieldValue('hw-법인', asset.);
setFieldValue('hw-자산코드', asset.);
setFieldValue('hw-현사용조직', asset.);
setFieldValue('hw-이전사용조직', asset.);
setFieldValue('hw-상세용도', (asset as any).);
parseAndSetLocation(asset., 'hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타-group', 'hw-위치-기타');
setFieldValue('hw-모델명', asset.);
setFieldValue('hw-OS', asset.OS);
setFieldValue('hw-CPU', asset.CPU);
setFieldValue('hw-RAM', asset.RAM);
setFieldValue('hw-SSD1', asset.SSD1);
setFieldValue('hw-SSD2', asset.SSD2);
setFieldValue('hw-담당자_정', asset._정 || asset.);
setFieldValue('hw-담당자_부', asset._부);
const isServerGrade = asset.type === '서버' || (asset as any). === '서버' || asset.type === '스토리지' || ['NAS', 'DAS'].includes(asset.type);
if (isServerGrade) {
setFieldValue('hw-용도', asset. || (asset as any).purpose);
setFieldValue('hw-상세', asset. || (asset as any).details);
setFieldValue('hw-비고', asset. || (asset as any).remarks);
setFieldValue('hw-구매일', asset. || (asset as any).purchase_date);
setFieldValue('hw-유형', asset.storage유형 || asset.type);
setFieldValue('hw-IP주소', asset.IP주소 || (asset as any).ip_address);
setFieldValue('hw-IP2', (asset as any).IP2 || (asset as any).ip_address_2);
setFieldValue('hw-원격접속', asset. || (asset as any).remote_tool);
setFieldValue('hw-서버ID', (asset as any).ID || (asset as any).server_id);
setFieldValue('hw-서버PW', (asset as any).PW || (asset as any).server_pw);
setFieldValue('hw-모니터링', asset. || (asset as any).monitoring);
} else {
setFieldValue('hw-명칭', asset. || asset.);
setFieldValue('hw-구매일', asset. || (asset as any).purchase_date);
setFieldValue('hw-금액', asset. || (asset as any).price);
setFieldValue('hw-HW사양', asset.HW사양 || asset. || (asset as any).details);
setFieldValue('hw-IP주소-non-server', asset.IP주소 || (asset as any).ip_address);
}
}
export function initHwModal(onSave: () => void, closeModals: () => void) {
// HTML 주입
if (!document.getElementById('hw-asset-modal')) {
document.body.insertAdjacentHTML('beforeend', HW_MODAL_HTML);
}
const modal = document.getElementById('hw-asset-modal')!;
const form = document.getElementById('hw-asset-form') as HTMLFormElement;
const closeBtn = document.getElementById('btn-close-hw-modal')!;
const cancelBtn = document.getElementById('btn-cancel-hw-modal')!;
const saveBtn = document.getElementById('btn-save-hw-asset')!;
const revertBtn = document.getElementById('btn-revert-hw-edit')!;
const deleteBtn = document.getElementById('btn-delete-hw-asset')!;
const typeSelect = document.getElementById('hw-유형') as HTMLSelectElement;
const detailPurposeSelect = document.getElementById('hw-상세용도') as HTMLSelectElement;
[typeSelect, detailPurposeSelect].forEach(el => {
el?.addEventListener('change', () => applyTypeSpecificUI(typeSelect.value));
});
const closeModal = () => {
closeModals();
bindLocationEvents('hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타-group', 'hw-위치-기타');
const closeModalAction = () => { closeModals(); isEditMode = false; };
document.getElementById('btn-close-hw-modal')?.addEventListener('click', closeModalAction);
document.getElementById('btn-cancel-hw-modal')?.addEventListener('click', closeModalAction);
revertBtn.addEventListener('click', () => {
setEditLock('hw-asset-form', 'view', {
saveBtnId: 'btn-save-hw-asset',
revertBtnId: 'btn-revert-hw-edit',
generateBtnId: 'btn-generate-hw-code'
});
isEditMode = false;
};
if (currentAsset) fillHwFormData(currentAsset);
});
const switchToViewMode = () => {
isEditMode = false;
form.classList.remove('is-edit-mode');
form.classList.add('is-view-mode');
saveBtn.textContent = '수정';
revertBtn.classList.add('hidden');
if (currentAsset) fillHwFormData(currentAsset);
};
closeBtn.addEventListener('click', closeModal);
cancelBtn.addEventListener('click', closeModal);
modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(); });
revertBtn.addEventListener('click', () => { switchToViewMode(); });
document.getElementById('btn-generate-hw-code')?.addEventListener('click', async () => {
const typeValue = typeSelect.value;
const purchaseDate = getFieldValue('hw-구매일');
const typeCode = TYPE_PREFIX_MAP[typeValue] || 'ETC';
const dateStr = purchaseDate.replace(/[^0-9]/g, '');
if (dateStr.length < 4) { alert('올바른 구매일(연월)을 입력해주세요.'); return; }
const prefix = `${typeCode}-${dateStr.substring(2, 6)}-`;
try {
const res = await fetch(`http://localhost:3000/api/generate-asset-code?prefix=${prefix}`);
const data = await res.json();
if (data.nextCode) setFieldValue('hw-자산코드', data.nextCode);
} catch (err) { alert('자산번호 생성에 실패했습니다.'); }
});
saveBtn.addEventListener('click', () => {
if (!currentAsset) return;
if (!isEditMode) {
setEditLock('hw-asset-form', 'edit', {
saveBtnId: 'btn-save-hw-asset',
revertBtnId: 'btn-revert-hw-edit'
});
isEditMode = true;
form.classList.remove('is-view-mode');
form.classList.add('is-edit-mode');
saveBtn.textContent = '저장';
revertBtn.classList.remove('hidden');
return;
}
const assetId = (document.getElementById('hw-asset-id') as HTMLInputElement).value;
const type = (document.getElementById('hw-asset-type') as HTMLInputElement).value;
const updated: HardwareAsset = {
const type = typeSelect.value;
const detailPurpose = detailPurposeSelect.value;
const updated: any = {
...currentAsset,
: (document.getElementById('hw-법인') as HTMLInputElement).value,
: (document.getElementById('hw-자산코드') as HTMLInputElement).value,
: (document.getElementById('hw-위치') as HTMLInputElement).value,
: (document.getElementById('hw-모델명') as HTMLInputElement).value,
OS: (document.getElementById('hw-OS') as HTMLInputElement).value,
CPU: (document.getElementById('hw-CPU') as HTMLInputElement).value,
RAM: (document.getElementById('hw-RAM') as HTMLInputElement).value,
SSD1: (document.getElementById('hw-SSD1') as HTMLInputElement).value,
SSD2: (document.getElementById('hw-SSD2') as HTMLInputElement).value,
_정: (document.getElementById('hw-담당자_정') as HTMLInputElement).value,
: (document.getElementById('hw-담당자_정') as HTMLInputElement).value,
_부: (document.getElementById('hw-담당자_') as HTMLInputElement).value,
법인: getFieldValue('hw-법인'),
자산코드: getFieldValue('hw-자산코드'),
현사용조직: getFieldValue('hw-현사용조직'),
이전사용조직: getFieldValue('hw-이전사용조직'),
위치: getCombinedLocation('hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타'),
모델명: getFieldValue('hw-모델명'),
OS: getFieldValue('hw-OS'),
CPU: getFieldValue('hw-CPU'),
RAM: getFieldValue('hw-RAM'),
SSD1: getFieldValue('hw-SSD1'),
SSD2: getFieldValue('hw-SSD2'),
담당자_정: getFieldValue('hw-담당자_'),
관리자: getFieldValue('hw-담당자_정'),
담당자_부: getFieldValue('hw-담당자_부'),
type: type,
상세용도: detailPurpose
};
if (type === '서버') {
updated. = (document.getElementById('hw-용도') as HTMLInputElement).value;
updated. = (document.getElementById('hw-상세') as HTMLInputElement).value;
updated. = (document.getElementById('hw-비고') as HTMLInputElement).value;
updated.IP주소 = (document.getElementById('hw-IP주소') as HTMLInputElement).value;
(updated as any).IP2 = (document.getElementById('hw-IP2') as HTMLInputElement).value;
updated. = (document.getElementById('hw-원격접속') as HTMLInputElement).value;
(updated as any).ID = (document.getElementById('hw-서버ID') as HTMLInputElement).value;
(updated as any).PW = (document.getElementById('hw-서버PW') as HTMLInputElement).value;
updated. = (document.getElementById('hw-모니터링') as HTMLInputElement).value;
if (type === '서버' || (type === 'PC' && detailPurpose === '서버') || ['스토리지', 'NAS', 'DAS'].includes(type)) {
updated. = getFieldValue('hw-용도');
updated. = getFieldValue('hw-상세');
updated. = getFieldValue('hw-비고');
updated.storage유형 = type;
updated.IP주소 = getFieldValue('hw-IP주소');
updated.IP2 = getFieldValue('hw-IP2');
updated. = getFieldValue('hw-원격접속');
updated.ID = getFieldValue('hw-서버ID');
updated.PW = getFieldValue('hw-서버PW');
updated. = getFieldValue('hw-모니터링');
} else {
updated. = (document.getElementById('hw-명칭') as HTMLInputElement).value;
updated. = (document.getElementById('hw-구매일') as HTMLInputElement).value;
updated. = (document.getElementById('hw-금액') as HTMLInputElement).value;
updated.HW사양 = (document.getElementById('hw-HW사양') as HTMLTextAreaElement).value;
updated.IP주소 = (document.getElementById('hw-IP주소-non-server') as HTMLInputElement).value;
if (type === '전산비품') {
updated. = (document.getElementById('hw-비품유형') as HTMLSelectElement).value;
}
updated. = getFieldValue('hw-명칭');
updated. = getFieldValue('hw-구매일');
updated. = getFieldValue('hw-금액');
updated.HW사양 = getFieldValue('hw-HW사양');
updated.IP주소 = getFieldValue('hw-IP주소-non-server');
}
const idx = state.masterData.hw.findIndex(a => a.id === assetId);
if (idx > -1) {
state.masterData.hw[idx] = updated;
onSave();
switchToViewMode();
}
saveHardwareAsset(updated);
onSave();
setEditLock('hw-asset-form', 'view', {
saveBtnId: 'btn-save-hw-asset',
revertBtnId: 'btn-revert-hw-edit'
});
isEditMode = false;
});
deleteBtn.addEventListener('click', () => {
if (!currentAsset) return;
if (confirm('정말로 이 자산을 삭제하시겠습니까?')) {
state.masterData.hw = state.masterData.hw.filter(a => a.id !== currentAsset!.id);
deleteHardwareAsset(currentAsset.id);
onSave();
closeModal();
closeModals();
}
});
}