From 9365af452238063ee4ce33fd3cd63e8c4dc38d63 Mon Sep 17 00:00:00 2001 From: Taehoon Date: Thu, 23 Apr 2026 18:00:10 +0900 Subject: [PATCH] feat: implement unified schema mapper, enhance UI/UX with responsive design, and optimize asset log logic --- image 92.png | Bin 0 -> 137899 bytes index.html | 121 ++++++------ server.js | 2 +- src/components/Guide.ts | 142 +++++++++++--- src/components/Modal/CloudModal.ts | 4 +- src/components/Modal/HWModal.ts | 245 +++++++++++------------- src/components/Modal/SWModal.ts | 111 +++++------ src/components/Navigation.ts | 34 ++-- src/core/schema.ts | 74 ++++++++ src/main.ts | 112 ++++------- src/styles/common.css | 234 ++++++++++++++++++++--- src/styles/guide.css | 281 ++++++---------------------- src/styles/table.css | 83 +++++--- src/views/List/CloudListView.ts | 71 +++---- src/views/List/EquipmentListView.ts | 91 ++++----- src/views/List/MobileListView.ts | 95 +++++----- src/views/List/PcListView.ts | 90 ++++++--- src/views/List/ServerListView.ts | 70 ++++--- src/views/List/StorageListView.ts | 73 +++++--- src/views/List/SwListView.ts | 79 ++++---- src/views/SW_Table.ts | 9 +- 21 files changed, 1129 insertions(+), 892 deletions(-) create mode 100644 image 92.png create mode 100644 src/core/schema.ts diff --git a/image 92.png b/image 92.png new file mode 100644 index 0000000000000000000000000000000000000000..5a36e8f82330330a26f719fa3fd44fae396db00e GIT binary patch literal 137899 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

$G>X*FP&sG)+jYX*M7^sig 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 - - - - - ITAM 자산관리 ERP - - - - - - - - - - -

- -
- +
+ + +
+ +
+ + +
+

Powered by BARON Consultant Co,Ltd

+
+
+ + + + + + \ No newline at end of file diff --git a/server.js b/server.js index c5d0b95..60f0baa 100644 --- a/server.js +++ b/server.js @@ -370,7 +370,7 @@ app.get('/api/generate-asset-code', async (req, res) => { }); } - const nextNum = (maxNum + 1).toString().padStart(3, '0'); + const nextNum = (maxNum + 1).toString().padStart(4, '0'); res.json({ nextCode: `${prefix}${nextNum}` }); } catch (err) { res.status(500).json({ error: err.message }); diff --git a/src/components/Guide.ts b/src/components/Guide.ts index ef643e7..932ef18 100644 --- a/src/components/Guide.ts +++ b/src/components/Guide.ts @@ -1,6 +1,7 @@ import { createIcons, BookOpen, X, ChevronDown, ChevronRight, RefreshCw } from 'lucide'; +import { state } from '../core/state'; -// ─── 자산별 가이드 콘텐츠 정의 ─── +// ─── 자산별 가이드 콘텐츠 정의 (SW_Table 브랜치 전체 복구) ─── interface GuideTabConfig { id: string; label: string; @@ -46,6 +47,21 @@ const GUIDE_TABS: GuideTabConfig[] = [ + +
+

시스템 기본 사용방법

+ + + + + + + + + + +
기능방법
자산 조회상단 카테고리(하드웨어/소프트웨어) 및 하위 탭 선택 후 데이터 조회
자산 등록[자산 추가] 버튼 클릭 후 상세 정보 입력 및 저장
정보 수정목록 행 클릭 후 나타나는 모달에서 내용 변경 및 저장
엑셀 업로드[업로드] 버튼 선택 후 표준 양식의 .xlsx 파일 선택
전체 엑셀저장[엑셀저장] 버튼 클릭 시 현재 전체 자산 데이터를 Excel로 백업
표준 양식[양식] 버튼 클릭 시 데이터 업로드용 빈 양식 다운로드
+
` }, { @@ -55,7 +71,7 @@ const GUIDE_TABS: GuideTabConfig[] = [

개인PC 관리 가이드

- 개인PC는 임직원에게 지급되는 데스크톱 및 노트북을 관리합니다. 자산의 지급, 교체, 반납까지의 전체 생애주기를 시스템에서 추적합니다. + 임직원에게 지급되는 데스크톱 및 노트북을 관리합니다. 자산의 지급, 교체, 반납까지의 전체 생애주기를 시스템에서 추적합니다.

@@ -70,33 +86,63 @@ const GUIDE_TABS: GuideTabConfig[] = [
2 -
자산 등록

자산코드 부여, 사양(CPU/RAM/Storage) 등록

+
자산 등록

자산번호 부여, 상세 사양 등록

3 -
사용자 지급

사용자·사용조직 지정, 설치위치 기록

+
사용자 지급

사용자 지정 및 설치위치 기록

4 -
운영 관리

OS 업데이트, 보안 점검, 품의서 관리

+
운영 관리

보안 점검 및 수리 이력 관리

+
+
+ +
+
+ 5 +
교체/반납

장비 회수 및 데이터 소거

+
+ +
+ 6 +
폐기 처리

불용 처리 및 매각/폐기 등록

+ +
+

주요 관리 항목

+ + + + + + + + + +
항목설명관리 주기
구매법인자산의 소유 법인등록 시
사용자/조직실제 사용자 및 소속 부서변동 시
자산번호고유 식별 번호 (바코드)등록 시
모델명/사양제조사 모델 및 CPU/RAM 등등록 시
도입금액구매 비용 (부가세 포함)등록 시
+
+ +
+ 관리 팁: 자산 이력에서 '분출'과 '반납' 로그를 꼼꼼히 기록하면 자산의 실제 위치를 정확히 파악할 수 있습니다. +
` }, { id: 'server', - label: '🖥️ 서버', + label: '🖥️ 서버/스토리지', content: `
-

서버 관리 가이드

+

인프라 자산 관리 가이드

- 물리 서버와 가상 서버를 포함한 서버급 자산을 관리합니다. 안정적인 서비스 운영을 위해 체계적인 관리가 필요합니다. + 서버실 및 IDC에 설치된 물리 서버와 스토리지 장비를 관리합니다. 고가의 자산이므로 담당자(정/부) 지정이 필수입니다.

@@ -106,21 +152,66 @@ const GUIDE_TABS: GuideTabConfig[] = [
1 -
도입 계획

용도 정의, 사양 산정, 구매 승인

+
도입 계획

사양 확정 및 구매 승인

2 -
설치 및 등록

랙 배치, 네트워크 설정, 자산 등록

+
설치 및 등록

네트워크 설정 및 자산번호 부여

3 -
운영 관리

모니터링, 패치 적용, 장애 대응

+
운영 관리

정기 점검 및 장애 이력 관리

+ +
+

필수 입력 항목

+ + + + + + + + +
항목중요성
IP 주소서버 접속 및 모니터링을 위한 필수 정보
설치위치IDC 또는 서버실 내의 정확한 랙 위치
담당자(정/부)비상 시 연락 가능한 관리 책임자
용도/상세운영 중인 서비스 및 상세 업무 설명
+
+ +
+ 주의 사항: 서버 자산의 IP가 변경될 경우 시스템에 즉시 반영하여 네트워크 관리 대장과의 정합성을 유지해야 합니다. +
+ ` + }, + { + id: 'software', + label: '💾 소프트웨어', + content: ` +
+

소프트웨어 자산 관리 가이드

+

+ 구독형(SaaS) 및 영구형 라이선스를 관리합니다. 불법 소프트웨어 사용 방지와 비용 최적화가 주 목적입니다. +

+
+ +
+

라이선스 관리 포인트

+ + + + + + + +
구분관리 내용
구독형(Sub)구독 만료일 도래 전 갱신 여부 결정 및 비용 정산
영구형(Perm)보유 수량 대비 실제 설치 수량 매핑 (초과 사용 금지)
운영서비스도메인, 메일 등 매월 또는 매년 발생하는 비용 추적
+
+ +
+ 팁: 소프트웨어 상세 페이지의 [사용자 할당] 기능을 활용하여 누가 어떤 라이선스를 사용하는지 체계적으로 관리하세요. +
` } ]; @@ -131,7 +222,7 @@ export function initGuide() { if (document.getElementById('guide-overlay')) return; const overlay = document.createElement('div'); - overlay.className = 'guide-overlay'; + overlay.className = 'modal-overlay hidden'; overlay.id = 'guide-overlay'; const tabsHtml = GUIDE_TABS.map((tab, i) => @@ -143,32 +234,33 @@ export function initGuide() { ).join(''); overlay.innerHTML = ` -
-
-

IT 자산관리 프로세스 가이드

-
-
${tabsHtml}
-
${panelsHtml}
+
+
${tabsHtml}
+
+
`; body.appendChild(overlay); const openGuide = () => { - console.log('📖 Opening Guide Modal...'); - overlay.classList.add('active'); + console.log('📖 Opening Full Guide Modal...'); + overlay.classList.remove('hidden'); }; - const closeGuide = () => overlay.classList.remove('active'); + const closeGuide = () => overlay.classList.add('hidden'); const triggerBtn = document.getElementById('btn-open-guide-header'); if (triggerBtn) { - console.log('✅ Guide trigger button found and bound.'); triggerBtn.addEventListener('click', openGuide); - } else { - console.warn('⚠️ Guide trigger button (#btn-open-guide-header) not found in DOM.'); } overlay.addEventListener('click', (e) => { if (e.target === overlay) closeGuide(); }); @@ -187,5 +279,5 @@ export function initGuide() { }); }); - createIcons({ icons: { BookOpen, X, ChevronDown, ChevronRight, RefreshCw }, nameAttr: 'data-lucide' }); + createIcons({ icons: { BookOpen, X, ChevronDown, ChevronRight, RefreshCw } }); } diff --git a/src/components/Modal/CloudModal.ts b/src/components/Modal/CloudModal.ts index eba98e1..97b7ed2 100644 --- a/src/components/Modal/CloudModal.ts +++ b/src/components/Modal/CloudModal.ts @@ -221,7 +221,7 @@ export function initCloudModal(renderContent: () => void, closeModals: () => voi id: Math.random().toString(36).substring(2, 9), assetId: newAsset.id, date: `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`, - user: '관리자', + user: '담당자', details: '신규 등록' }); } @@ -271,7 +271,7 @@ export function initCloudModal(renderContent: () => void, closeModals: () => voi id: Math.random().toString(36).substring(2, 9), assetId: id, date, - user: '관리자', + user: '담당자', details }); diff --git a/src/components/Modal/HWModal.ts b/src/components/Modal/HWModal.ts index 005e51b..b87c03f 100644 --- a/src/components/Modal/HWModal.ts +++ b/src/components/Modal/HWModal.ts @@ -1,6 +1,7 @@ import { state, saveHardwareAsset, deleteHardwareAsset } from '../../core/state'; -import { HardwareAsset, HardwareLog } from '../../core/excelHandler'; +import { HardwareAsset } from '../../core/excelHandler'; import { closeModals } from './BaseModal'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; import { createIcons, History, Plus, X, Save, Edit2, RotateCcw, Paperclip } from 'lucide'; import { CORP_LIST, ORG_LIST, HW_TYPE_LIST, LOCATION_DATA, TYPE_PREFIX_MAP } from './SharedData'; import { @@ -21,62 +22,64 @@ let isEditMode = false; const STATUS_LIST = ['대여중', '보관중', '수리중', '기타']; -// 필드 ID ↔ 데이터 Key 매핑 (유지보수 시 이 부분만 수정) +/** + * 하드웨어 필드 매핑 (통합 스키마 기반) + */ const HW_FIELD_MAP: Record = { - '유형': 'type', - '법인': '법인', - '자산코드': '자산코드', - '현사용조직': '현사용조직', - '이전사용조직': '이전사용조직', - '상세용도': '상세용도', - '모델명': '모델명', - '명칭': '명칭', - '보관위치': '보관위치', - '현재상태': '현재상태', - 'IP주소': 'IP주소', - 'IP2': 'IP2', - '원격접속': '원격접속', - '서버ID': '서버ID', - '서버PW': '서버PW', - '모니터링': '모니터링', - 'OS': 'OS', - 'CPU': 'CPU', - 'RAM': 'RAM', - 'SSD1': 'SSD1', - 'SSD2': 'SSD2', - 'HW사양': 'HW사양', - '담당자_정': '담당자_정', - '담당자_부': '담당자_부', - '구매일': '구매연월', - '금액': '금액', - '비고': '비고', - '사용자': '사용자' + '유형': ASSET_SCHEMA.TYPE.key, + '법인': ASSET_SCHEMA.CORP.key, + '자산코드': ASSET_SCHEMA.ASSET_CODE.key, + '현사용조직': ASSET_SCHEMA.ORG.key, + '이전사용조직': ASSET_SCHEMA.PREV_ORG.key, + '상세용도': '상세용도', + '모델명': ASSET_SCHEMA.MODEL.key, + '메인보드': ASSET_SCHEMA.MAINBOARD.key, + '명칭': '명칭', + '보관위치': ASSET_SCHEMA.STORE_LOC.key, + '현재상태': ASSET_SCHEMA.STATUS.key, + 'IP주소': ASSET_SCHEMA.IP_ADDR.key, + 'IP2': ASSET_SCHEMA.IP_ADDR2.key, + '원격접속': '원격접속', + '서버ID': '서버ID', + '서버PW': '서버PW', + '모니터링': '모니터링', + 'OS': ASSET_SCHEMA.OS.key, + 'CPU': ASSET_SCHEMA.CPU.key, + 'RAM': ASSET_SCHEMA.RAM.key, + 'SSD1': ASSET_SCHEMA.STORAGE1.key, + 'SSD2': ASSET_SCHEMA.STORAGE2.key, + 'HW사양': 'HW사양', + '담당자_정': ASSET_SCHEMA.MANAGER_MAIN.key, + '담당자_부': ASSET_SCHEMA.MANAGER_SUB.key, + '구매일': ASSET_SCHEMA.PURCHASE_YM.key, + '금액': ASSET_SCHEMA.PRICE.key, + '비고': ASSET_SCHEMA.REMARKS.key, + '사용자': ASSET_SCHEMA.USER.key }; const HW_FORM_HTML = ` -
기본 정보 (Identity)
- +
- +
- +
- +
- +
@@ -94,29 +97,30 @@ const HW_FORM_HTML = `
운영 및 상태 관리
- +
- +
네트워크 정보 (Connectivity)
-
-
+
+
-
+
시스템 사양 (Specifications)
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -124,13 +128,13 @@ const HW_FORM_HTML = `
-
-
-
-
-
+
+
+
+
+
- +
@@ -162,6 +166,7 @@ function applyTypeSpecificUI(type: string) { specTitle: document.getElementById('hw-spec-title'), opTitle: document.getElementById('hw-op-title'), model: document.getElementById('hw-model-group'), + mainboard: document.getElementById('hw-mainboard-group'), os: document.getElementById('hw-os-group'), cpu: document.getElementById('hw-cpu-group'), ram: document.getElementById('hw-ram-group'), @@ -177,7 +182,6 @@ function applyTypeSpecificUI(type: string) { const opOnly = document.querySelectorAll('.op-only'); const standardLoc = document.querySelectorAll('.loc-standard'); - // 초기화 serverOnly.forEach(el => (el as HTMLElement).style.display = 'none'); nonServer.forEach(el => (el as HTMLElement).style.display = 'none'); opOnly.forEach(el => (el as HTMLElement).style.display = 'none'); @@ -187,9 +191,9 @@ function applyTypeSpecificUI(type: string) { const osLabel = document.querySelector('label[for="hw-OS"]') as HTMLElement; const ramLabel = document.querySelector('label[for="hw-RAM"]') as HTMLElement; const modelLabel = document.querySelector('label[for="hw-모델명"]') as HTMLElement; - if (osLabel) osLabel.innerText = '운영체제 (OS)'; - if (ramLabel) ramLabel.innerText = 'RAM 용량'; - if (modelLabel) modelLabel.innerText = '모델명'; + if (osLabel) osLabel.innerText = ASSET_SCHEMA.OS.ui; + if (ramLabel) ramLabel.innerText = ASSET_SCHEMA.RAM.ui; + if (modelLabel) modelLabel.innerText = ASSET_SCHEMA.MODEL.ui; const isMobileGroup = ['모바일', '태블릿', '휴대폰'].some(t => upperType.includes(t)); const isEquipGroup = ['CPU', 'RAM', 'HDD', 'GPU'].some(t => upperType.includes(t)) || upperType.includes('비품'); @@ -208,7 +212,6 @@ function applyTypeSpecificUI(type: string) { if (groups.os && osLabel) { osLabel.innerText = '출시연월'; groups.os.style.display = 'flex'; } } else if (['RAM', 'HDD'].some(t => upperType.includes(t))) { if (groups.ram && ramLabel) { ramLabel.innerText = '용량'; groups.ram.style.display = 'flex'; } - if (upperType.includes('HDD') && modelLabel) modelLabel.innerText = 'S/N'; } else { if (groups.hwSpec) groups.hwSpec.style.display = 'flex'; } @@ -216,8 +219,8 @@ function applyTypeSpecificUI(type: string) { else if (isPcType) { if (groups.user) groups.user.style.display = 'flex'; if (groups.specTitle) groups.specTitle.style.display = 'flex'; + if (groups.mainboard) groups.mainboard.style.display = 'flex'; - // 노트북은 상세유형 선택창 숨김 if (upperType === '노트북') { if (groups.detailPurpose) groups.detailPurpose.style.display = 'none'; nonServer.forEach(el => (el as HTMLElement).style.display = 'flex'); @@ -254,13 +257,11 @@ export function openHwModal(asset: HardwareAsset, mode: 'view' | 'add' = 'view') }); isEditMode = (mode === 'add'); - - // 데이터 채우기 (자동 매핑) autoFillForm('hw', asset, HW_FIELD_MAP); - setFieldValue('hw-명칭', asset.명칭 || asset.모델명); - if (!asset.구매연월 && asset.구매일) setFieldValue('hw-구매일', asset.구매일); + setFieldValue('hw-명칭', asset.명칭 || asset[ASSET_SCHEMA.MODEL.key]); + if (!asset[ASSET_SCHEMA.PURCHASE_YM.key] && asset.구매일) setFieldValue('hw-구매일', asset.구매일); - parseAndSetLocation(asset.위치, 'hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타-group', 'hw-위치-기타'); + parseAndSetLocation(asset[ASSET_SCHEMA.LOCATION.key], 'hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타-group', 'hw-위치-기타'); applyTypeSpecificUI(asset.type); renderHwHistory(asset.id); @@ -276,18 +277,17 @@ export function initHwModal(onSave: () => void, closeModalsCb: () => void) { }); document.body.insertAdjacentHTML('beforeend', html); - // 이력 추가 모달 HTML도 함께 추가 const logModalHTML = ` `; @@ -338,15 +338,12 @@ export function initHwModal(onSave: () => void, closeModalsCb: () => void) { } catch (err) { alert('자산번호 생성에 실패했습니다.'); } }); - // YYYYMM 입력 제한 로직 (숫자 6자리) ['hw-구매일', 'hw-OS'].forEach(id => { const el = document.getElementById(id) as HTMLInputElement; el?.addEventListener('input', (e) => { const target = e.target as HTMLInputElement; const label = document.querySelector(`label[for="${id}"]`) as HTMLElement; - // OS 필드의 경우 라벨이 '출시연월'일 때만 숫자 제한 적용 if (id === 'hw-OS' && label?.innerText !== '출시연월') return; - target.value = target.value.replace(/[^0-9]/g, '').substring(0, 6); }); }); @@ -365,10 +362,8 @@ export function initHwModal(onSave: () => void, closeModalsCb: () => void) { return; } - // 데이터 추출 (자동 매핑) const extracted = autoExtractForm('hw', HW_FIELD_MAP); - - if (!extracted.자산코드) { + if (!extracted[ASSET_SCHEMA.ASSET_CODE.key]) { alert('자산번호가 없습니다. [생성] 버튼을 눌러 자산번호를 먼저 부여해주세요.'); return; } @@ -376,51 +371,52 @@ export function initHwModal(onSave: () => void, closeModalsCb: () => void) { const upperType = (extracted.type || '').toUpperCase(); const isOpType = ['CPU', 'RAM', 'HDD', 'GPU'].some(t => upperType.includes(t)) || upperType.includes('비품') || ['모바일', '태블릿', '휴대폰'].some(t => upperType.includes(t)); - // --- 자동 변경 이력 생성 로직 --- - // 모든 하드웨어 유형에 대해 자동 로깅 적용 if (HW_TYPE_LIST.includes(extracted.type) || extracted.type === '개인PC') { const diffLogs: string[] = []; const compareFields = [ - { key: '현사용조직', label: '현사용조직' }, - { key: '위치', label: '설치위치' }, - { key: '관리자', label: '담당자' }, - { key: '현재상태', label: '상태' }, - { key: 'IP주소', label: 'IP' }, + { key: ASSET_SCHEMA.ORG.key, label: ASSET_SCHEMA.ORG.ui }, + { key: ASSET_SCHEMA.LOCATION.key, label: ASSET_SCHEMA.LOCATION.ui }, + { key: ASSET_SCHEMA.MANAGER_MAIN.key, label: '담당자' }, + { key: ASSET_SCHEMA.STATUS.key, label: ASSET_SCHEMA.STATUS.ui }, + { key: ASSET_SCHEMA.IP_ADDR.key, label: ASSET_SCHEMA.IP_ADDR.ui }, { key: '상세용도', label: '상세유형' }, - { key: '모델명', label: '모델명' } + { key: ASSET_SCHEMA.MODEL.key, label: ASSET_SCHEMA.MODEL.ui } ]; - const currentIp = currentAsset.IP주소 || ''; - const newIp = getFieldValue('hw-IP주소') || getFieldValue('hw-IP주소-non-server'); - const currentLocation = currentAsset.위치 || ''; - const newLocation = isOpType ? extracted.보관위치 : getCombinedLocation('hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타'); + const isNewAsset = !currentAsset || !currentAsset.자산코드; - compareFields.forEach(f => { - let oldVal = ''; - let newVal = ''; + if (isNewAsset) { + diffLogs.push('자산 신규 등록'); + } else { + const newIp = String(getFieldValue('hw-IP주소') || getFieldValue('hw-IP주소-non-server') || '').trim(); + const newLocation = String(isOpType ? extracted[ASSET_SCHEMA.STORE_LOC.key] : getCombinedLocation('hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타') || '').trim(); - if (f.key === 'IP주소') { - oldVal = currentIp; - newVal = newIp; - } else if (f.key === '위치') { - oldVal = currentLocation; - newVal = newLocation; - } else if (f.key === '관리자') { - oldVal = currentAsset.담당자_정 || ''; - newVal = extracted.담당자_정 || ''; - } else if (f.key === '상세용도') { - oldVal = currentAsset.상세용도 || ''; - // 비 PC 자산은 유형을 상세유형으로 간주 - newVal = (extracted.type !== 'PC' && extracted.type !== '개인PC') ? extracted.type : (extracted.상세용도 || ''); - } else { - oldVal = (currentAsset as any)[f.key] || ''; - newVal = extracted[f.key] || ''; - } + compareFields.forEach(f => { + let oldVal = ''; + let newVal = ''; - if (oldVal !== newVal) { - diffLogs.push(`${f.label}: ${oldVal || '(없음)'} → ${newVal || '(없음)'}`); - } - }); + if (f.key === ASSET_SCHEMA.IP_ADDR.key) { + oldVal = String(currentAsset[ASSET_SCHEMA.IP_ADDR.key] || '').trim(); + newVal = newIp; + } else if (f.key === ASSET_SCHEMA.LOCATION.key) { + oldVal = String(currentAsset[ASSET_SCHEMA.LOCATION.key] || '').trim(); + newVal = newLocation; + } else if (f.key === ASSET_SCHEMA.MANAGER_MAIN.key) { + oldVal = String(currentAsset[ASSET_SCHEMA.MANAGER_MAIN.key] || '').trim(); + newVal = String(extracted[ASSET_SCHEMA.MANAGER_MAIN.key] || '').trim(); + } else if (f.key === '상세용도') { + oldVal = String(currentAsset.상세용도 || '').trim(); + newVal = String((extracted.type !== 'PC' && extracted.type !== '개인PC') ? extracted.type : (extracted.상세용도 || '')).trim(); + } else { + oldVal = String((currentAsset as any)[f.key] || '').trim(); + newVal = String(extracted[f.key] || '').trim(); + } + + if (oldVal !== newVal) { + diffLogs.push(`${f.label}: ${oldVal || '(없음)'} → ${newVal || '(없음)'}`); + } + }); + } if (diffLogs.length > 0) { state.masterData.logs = state.masterData.logs || []; @@ -428,44 +424,31 @@ export function initHwModal(onSave: () => void, closeModalsCb: () => void) { id: Math.random().toString(36).substring(2, 9), assetId: currentAsset.id, date: new Date().toISOString().split('T')[0], - user: '관리자', + user: '담당자', details: diffLogs.join('\n') }); } } - // ---------------------------- const updated: any = { ...currentAsset, ...extracted, - IP주소: getFieldValue('hw-IP주소') || getFieldValue('hw-IP주소-non-server'), - 관리자: extracted.담당자_정, - 위치: isOpType ? extracted.보관위치 : getCombinedLocation('hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타') + [ASSET_SCHEMA.IP_ADDR.key]: getFieldValue('hw-IP주소') || getFieldValue('hw-IP주소-non-server'), + 위치: isOpType ? extracted[ASSET_SCHEMA.STORE_LOC.key] : getCombinedLocation('hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타') }; - // 현 사용조직 변경 시 이전 사용조직 자동 업데이트 - if (currentAsset.현사용조직 && currentAsset.현사용조직 !== extracted.현사용조직) { - updated.이전사용조직 = currentAsset.현사용조직; + if (currentAsset[ASSET_SCHEMA.ORG.key] && currentAsset[ASSET_SCHEMA.ORG.key] !== extracted[ASSET_SCHEMA.ORG.key]) { + updated[ASSET_SCHEMA.PREV_ORG.key] = currentAsset[ASSET_SCHEMA.ORG.key]; } - - // 비 PC 자산에 대해 상세유형(상세용도)을 유형과 동기화 - if (updated.type !== 'PC') { - updated.상세용도 = updated.type; - } - + if (updated.type !== 'PC') { updated.상세용도 = updated.type; } saveHardwareAsset(updated); onSave(); - setEditLock('hw-asset-form', 'view', { - saveBtnId: 'btn-save-hw-asset', - revertBtnId: 'btn-revert-hw-edit', - generateBtnId: 'btn-generate-hw-code', - addLogBtnId: 'btn-add-hw-log' - }); + setEditLock('hw-asset-form', 'view', { saveBtnId: 'btn-save-hw-asset', revertBtnId: 'btn-revert-hw-edit', generateBtnId: 'btn-generate-hw-code', addLogBtnId: 'btn-add-hw-log' }); isEditMode = false; }); deleteBtn.addEventListener('click', () => { - if (currentAsset && confirm('정말로 삭제하시겠습니까?')) { + if (currentAsset && confirm(UI_TEXT.MESSAGES.CONFIRM_DELETE)) { deleteHardwareAsset(currentAsset.id); onSave(); closeModalAction(); @@ -486,7 +469,7 @@ export function initHwModal(onSave: () => void, closeModalsCb: () => void) { const details = (document.getElementById('new-hw-log-details') as HTMLTextAreaElement).value; if (!date || !details) return; state.masterData.logs = state.masterData.logs || []; - state.masterData.logs.push({ id: Math.random().toString(36).substring(2, 9), assetId: currentAsset.id, date, user: '관리자', details }); + state.masterData.logs.push({ id: Math.random().toString(36).substring(2, 9), assetId: currentAsset.id, date, user: '담당자', details }); logModal.classList.add('hidden'); renderHwHistory(currentAsset.id); }); diff --git a/src/components/Modal/SWModal.ts b/src/components/Modal/SWModal.ts index 4e8e556..59c9449 100644 --- a/src/components/Modal/SWModal.ts +++ b/src/components/Modal/SWModal.ts @@ -2,8 +2,9 @@ import { state } from '../../core/state'; import { SoftwareAsset } from '../../core/excelHandler'; import { closeModals } from './BaseModal'; import { openSwUserModal } from './SWUserModal'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; import { createIcons, History, Plus, X, Save, Edit2, RotateCcw } from 'lucide'; -import { CORP_LIST, TYPE_PREFIX_MAP } from './SharedData'; +import { CORP_LIST } from './SharedData'; import { generateOptionsHTML, setFieldValue, @@ -17,67 +18,63 @@ import { let currentSwAsset: SoftwareAsset | null = null; let isEditMode = false; +/** + * 소프트웨어 필드 매핑 (통합 스키마 기반) + * 소프트웨어는 자산번호를 사용하지 않으므로 제거함 + */ const SW_FIELD_MAP: Record = { - '법인': '법인', - '자산번호': '자산번호', - '제품명': '제품명', - '수량': '수량', - '금액': '금액', - '구매일': '구매일', - '납품업체': '납품업체', - '비고': '비고', - '플랫폼명': '플랫폼명', - '부서': '부서', - '계정명': '계정명', - '결제수단': '결제수단', - '연결카드번호': '연결카드번호', - '결제일': '결제일', - '당월청구액': '당월청구액', - '라이선스유형': '라이선스유형', - '만료일': '만료일', - '라이선스키': '라이선스키' + '법인': ASSET_SCHEMA.CORP.key, + '제품명': ASSET_SCHEMA.PRODUCT.key, + '수량': ASSET_SCHEMA.QTY.key, + '금액': ASSET_SCHEMA.PRICE.key, + '구매일': ASSET_SCHEMA.PURCHASE_YM.key, + '납품업체': ASSET_SCHEMA.VENDOR.key, + '비고': ASSET_SCHEMA.REMARKS.key, + '플랫폼명': ASSET_SCHEMA.PLATFORM.key, + '부서': '부서', + '계정명': ASSET_SCHEMA.ACCOUNT.key, + '결제수단': ASSET_SCHEMA.PAY_METHOD.key, + '연결카드번호': ASSET_SCHEMA.CARD_NUM.key, + '결제일': ASSET_SCHEMA.PAY_DAY.key, + '당월청구액': ASSET_SCHEMA.BILLING.key, + '라이선스유형': ASSET_SCHEMA.LICENSE_TYPE.key, + '만료일': ASSET_SCHEMA.EXPIRY.key, + '라이선스키': ASSET_SCHEMA.LICENSE_KEY.key }; const SW_FORM_HTML = `
기본 정보 (Identity)
- +
-
- -
- - -
-
- +
-
+
라이선스 및 계약 정보
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
관리 및 비고
-
-
-
-
+
+
+
+
@@ -149,7 +146,6 @@ export function openSwModal(asset: SoftwareAsset, mode: 'view' | 'add' = 'view') setEditLock('sw-asset-form', mode, { saveBtnId: 'btn-save-sw-asset', revertBtnId: 'btn-revert-sw-edit', - generateBtnId: 'btn-generate-sw-code', addLogBtnId: 'btn-add-sw-log' }); isEditMode = (mode === 'add'); @@ -171,9 +167,9 @@ export function initSwModal(onSave: () => void, closeModalsCb: () => void) { const logModalHTML = ` `; @@ -196,27 +192,12 @@ export function initSwModal(onSave: () => void, closeModalsCb: () => void) { setEditLock('sw-asset-form', 'view', { saveBtnId: 'btn-save-sw-asset', revertBtnId: 'btn-revert-sw-edit', - generateBtnId: 'btn-generate-sw-code', addLogBtnId: 'btn-add-sw-log' }); isEditMode = false; if (currentSwAsset) openSwModal(currentSwAsset, 'view'); }); - document.getElementById('btn-generate-sw-code')?.addEventListener('click', async () => { - const typeValue = getFieldValue('sw-asset-type'); - const purchaseDate = getFieldValue('sw-구매일'); - const typeCode = TYPE_PREFIX_MAP[typeValue] || 'SW'; - const dateStr = purchaseDate.replace(/[^0-9]/g, ''); - if (dateStr.length < 6) { alert('올바른 구매연월(YYYYMM)을 입력해주세요.'); return; } - const prefix = `${typeCode}-${dateStr.substring(0, 6)}-`; - try { - const res = await fetch(`http://172.16.40.100:3000/api/generate-asset-code?prefix=${prefix}`); - const data = await res.json(); - if (data.nextCode) setFieldValue('sw-자산번호', data.nextCode); - } catch (err) { alert('자산번호 생성에 실패했습니다.'); } - }); - // YYYYMM 입력 제한 로직 (숫자 6자리) document.getElementById('sw-구매일')?.addEventListener('input', (e) => { const target = e.target as HTMLInputElement; @@ -229,14 +210,13 @@ export function initSwModal(onSave: () => void, closeModalsCb: () => void) { setEditLock('sw-asset-form', 'edit', { saveBtnId: 'btn-save-sw-asset', revertBtnId: 'btn-revert-sw-edit', - generateBtnId: 'btn-generate-sw-code', - addLogBtnId: 'btn-add-sw-log' + addLogBtnId: 'btn-add-hw-log' }); isEditMode = true; return; } const extracted = autoExtractForm('sw', SW_FIELD_MAP); - const updated = { ...currentSwAsset, ...extracted, 수량: parseInt(extracted.수량 || '0') }; + const updated = { ...currentSwAsset, ...extracted, 수량: parseInt(extracted[ASSET_SCHEMA.QTY.key] || '0') }; let targetList: SoftwareAsset[] = []; if (updated.type === '구독SW') targetList = state.masterData.subSw; @@ -250,14 +230,13 @@ export function initSwModal(onSave: () => void, closeModalsCb: () => void) { setEditLock('sw-asset-form', 'view', { saveBtnId: 'btn-save-sw-asset', revertBtnId: 'btn-revert-sw-edit', - generateBtnId: 'btn-generate-sw-code', addLogBtnId: 'btn-add-sw-log' }); isEditMode = false; }); deleteBtn.addEventListener('click', () => { - if (currentSwAsset && confirm('삭제하시겠습니까?')) { + if (currentSwAsset && confirm(UI_TEXT.MESSAGES.CONFIRM_DELETE)) { const type = currentSwAsset.type; if (type === '구독SW') state.masterData.subSw = state.masterData.subSw.filter(a => a.id !== currentSwAsset!.id); else if (type === '영구SW') state.masterData.permSw = state.masterData.permSw.filter(a => a.id !== currentSwAsset!.id); @@ -279,7 +258,7 @@ export function initSwModal(onSave: () => void, closeModalsCb: () => void) { const details = (document.getElementById('new-log-details') as HTMLTextAreaElement).value; if (!date || !details) return; state.masterData.logs = state.masterData.logs || []; - state.masterData.logs.push({ id: Math.random().toString(36).substring(2, 9), assetId: currentSwAsset.id, date, user: '관리자', details }); + state.masterData.logs.push({ id: Math.random().toString(36).substring(2, 9), assetId: currentSwAsset.id, date, user: '담당자', details }); logModal.classList.add('hidden'); renderSwHistory(currentSwAsset.id); }); } diff --git a/src/components/Navigation.ts b/src/components/Navigation.ts index 598eae9..7cabde5 100644 --- a/src/components/Navigation.ts +++ b/src/components/Navigation.ts @@ -7,11 +7,11 @@ const MENU_CONFIG = { }, sw: { label: '소프트웨어', - tabs: ['대시보드', '구독SW', '영구SW', '클라우드'] + tabs: ['대시보드', '구독SW', '영구SW'] }, ops: { label: '운영 서비스', - tabs: ['대시보드', '서비스현황', '백업관리', '보안점검'] + tabs: ['도메인', '메일', '메신저', '청구비용'] } }; @@ -22,6 +22,7 @@ export function renderNavigation(onTabChange: (tab: string) => void) { const render = () => { navContainer.innerHTML = ''; + // 기존 메뉴 렌더링 (Object.keys(MENU_CONFIG) as Array).forEach(catKey => { const config = MENU_CONFIG[catKey]; const isActive = state.activeCategory === catKey; @@ -29,7 +30,6 @@ export function renderNavigation(onTabChange: (tab: string) => void) { const group = document.createElement('div'); group.className = `nav-group ${isActive ? 'active is-showing-shelf' : ''}`; - // 메인 카테고리 트리거 const trigger = document.createElement('div'); trigger.className = 'gnb-trigger'; trigger.textContent = config.label; @@ -45,7 +45,6 @@ export function renderNavigation(onTabChange: (tab: string) => void) { }); group.appendChild(trigger); - // 하위 탭 선반 (Shelf) const shelf = document.createElement('div'); shelf.className = 'lnb-shelf'; @@ -58,21 +57,34 @@ export function renderNavigation(onTabChange: (tab: string) => void) { e.stopPropagation(); state.activeCategory = catKey; state.activeSubTab = tab; - - if (btnAddAsset) { - btnAddAsset.classList.remove('hidden'); - } - + if (btnAddAsset) btnAddAsset.classList.remove('hidden'); render(); onTabChange(tab); }); shelf.appendChild(item); }); group.appendChild(shelf); - - // 마우스 오버 시 다른 그룹의 선반은 가리고 내 것만 보여주는 스타일은 CSS에서 처리함 navContainer.appendChild(group); }); + + // ─── '관리자' 메뉴 별도 추가 (GNB 스타일) ─── + const adminGroup = document.createElement('div'); + adminGroup.className = 'nav-group'; + + const adminTrigger = document.createElement('div'); + adminTrigger.className = 'gnb-trigger'; + adminTrigger.innerHTML = '관리자'; + adminTrigger.style.color = 'var(--text-muted)'; + adminTrigger.style.borderLeft = '1px solid var(--border-color)'; + adminTrigger.style.marginLeft = '1rem'; + adminTrigger.style.paddingLeft = '1.5rem'; + + adminTrigger.addEventListener('click', () => { + alert('준비중입니다.'); + }); + + adminGroup.appendChild(adminTrigger); + navContainer.appendChild(adminGroup); }; render(); diff --git a/src/core/schema.ts b/src/core/schema.ts new file mode 100644 index 0000000..a0e8f83 --- /dev/null +++ b/src/core/schema.ts @@ -0,0 +1,74 @@ +/** + * ITAM 통합 스키마 매퍼 (Unified Schema Mapper) + * + * key: 애플리케이션 내부 로직에서 사용하는 속성명 + * db: MySQL 데이터베이스 컬럼명 + * ui: 사용자에게 보여지는 UI 레이블 + */ + +export const ASSET_SCHEMA = { + // ─── 공통 필드 (Common) ─── + ID: { key: 'id', db: 'id', ui: 'ID' }, + TYPE: { key: 'type', db: 'type', ui: '자산유형' }, + CORP: { key: '법인', db: 'corp', ui: '구매법인' }, + ASSET_CODE: { key: '자산코드', db: 'asset_code', ui: '자산번호' }, + PURCHASE_YM: { key: '구매연월', db: 'purchase_date', ui: '구매연월' }, + ORG: { key: '현사용조직', db: 'current_org', ui: '현 사용조직' }, + PREV_ORG: { key: '이전사용조직', db: 'prev_org', ui: '이전 사용조직' }, + LOCATION: { key: '위치', db: 'location', ui: '설치위치' }, + MANAGER_MAIN: { key: '담당자_정', db: 'manager_main', ui: '담당자' }, + MANAGER_SUB: { key: '담당자_부', db: 'manager_sub', ui: '담당자(부)' }, + PRICE: { key: '금액', db: 'price', ui: '도입금액' }, + VENDOR: { key: '납품업체', db: 'vendor', ui: '납품업체' }, + DOC_NAME: { key: '품의서명', db: 'doc_name', ui: '품의서' }, + REMARKS: { key: '비고', db: 'remarks', ui: '비고' }, + + // ─── 하드웨어 상세 (Hardware) ─── + USER: { key: '사용자', db: 'purpose', ui: '사용자' }, + MODEL: { key: '모델명', db: 'model_name', ui: '모델명' }, + MAINBOARD: { key: '메인보드', db: 'mainboard', ui: '메인보드' }, + OS: { key: 'OS', db: 'os', ui: '운영체제' }, + CPU: { key: 'CPU', db: 'cpu', ui: 'CPU' }, + RAM: { key: 'RAM', db: 'ram', ui: 'RAM' }, + STORAGE1: { key: 'SSD1', db: 'storage1', ui: 'Storage 1' }, + STORAGE2: { key: 'SSD2', db: 'storage2', ui: 'Storage 2' }, + IP_ADDR: { key: 'IP주소', db: 'ip_address', ui: 'IP 주소 1' }, + IP_ADDR2: { key: 'IP2', db: 'ip2', ui: 'IP 주소 2' }, + MAC_ADDR: { key: 'MACaddress', db: 'mac_address', ui: 'MAC 주소' }, + STATUS: { key: '현재상태', db: 'status', ui: '현재상태' }, + STORE_LOC: { key: '보관위치', db: 'storage_location',ui: '보관위치' }, + + // ─── 소프트웨어/클라우드 상세 (SW/Cloud) ─── + PRODUCT: { key: '제품명', db: 'product_name', ui: '제품/서비스명' }, + PLATFORM: { key: '플랫폼명', db: 'platform_name', ui: '운영 플랫폼' }, + LICENSE_TYPE: { key: '라이선스유형', db: 'license_type', ui: '라이선스 유형' }, + LICENSE_KEY: { key: '라이선스키', db: 'license_key', ui: '라이선스 키' }, + QTY: { key: '수량', db: 'quantity', ui: '보유수량' }, + EXPIRY: { key: '만료일', db: 'expiry_date', ui: '만료/구독일' }, + ACCOUNT: { key: '계정명', db: 'account_name', ui: '계정(이메일)' }, + PAY_METHOD: { key: '결제수단', db: 'pay_method', ui: '결제수단' }, + PAY_DAY: { key: '결제일', db: 'pay_day', ui: '결제일' }, + CARD_NUM: { key: '연결카드번호', db: 'card_num', ui: '카드번호(뒷4자리)' }, + BILLING: { key: '당월청구액', db: 'monthly_fee', ui: '당월 청구액' } +}; + +/** + * 용어 사전 (UI 텍스트 전용) + */ +export const UI_TEXT = { + ACTION: { + ADD: '신규 등록', + EDIT: '수정', + SAVE: '저장', + DELETE: '삭제', + CANCEL: '취소', + CLOSE: '닫기', + HISTORY_ADD: '이력 추가', + RESET_FILTER: '필터 초기화' + }, + MESSAGES: { + CONFIRM_DELETE: '정말로 삭제하시겠습니까?', + SAVE_SUCCESS: '성공적으로 저장되었습니다.', + NO_DATA: '검색 결과가 없습니다.' + } +}; diff --git a/src/main.ts b/src/main.ts index 23586bc..506aaed 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,14 +2,14 @@ import { state, loadMasterDataFromDB } from './core/state'; import { renderNavigation } from './components/Navigation'; import { renderDashboard } from './views/DashboardView'; import { renderSWTable } from './views/SW_Table'; -import { downloadTemplate, exportToExcel, parseExcel, HardwareAsset, SoftwareAsset, SWUser } from './core/excelHandler'; +import { downloadTemplate, exportToExcel, parseExcel } from './core/excelHandler'; import { initBaseModal } from './components/Modal/BaseModal'; import { initHwModal, openHwModal } from './components/Modal/HWModal'; import { initSwModal, openSwModal } from './components/Modal/SWModal'; import { initSwUserModal } from './components/Modal/SWUserModal'; import { initDashboardDetailModal } from './components/Modal/DashboardDetailModal'; import { initGuide } from './components/Guide'; -import { createIcons, Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, History, RefreshCcw } from 'lucide'; +import { createIcons, Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, History, RefreshCcw, BookOpen, Settings } from 'lucide'; // --- DB 저장을 위한 세분화된 헬퍼 함수들 --- async function apiBatchSave(url: string, data: any[], label: string) { @@ -36,72 +36,50 @@ const savePermSwToDB = () => apiBatchSave('http://172.16.40.100:3000/api/sw/perm const saveCloudToDB = () => apiBatchSave('http://172.16.40.100:3000/api/cloud/batch', state.masterData.cloud, '클라우드'); const saveSwUsersToDB = () => apiBatchSave('http://172.16.40.100:3000/api/sw-users/batch', state.masterData.swUsers, 'SW사용자'); -// 모든 하드웨어 DB 동기화 async function saveAllHardwareToDB() { - await Promise.all([ - savePcToDB(), - saveServerToDB(), - saveStorageToDB(), - saveEquipToDB(), - saveMobileToDB() - ]); + await Promise.all([savePcToDB(), saveServerToDB(), saveStorageToDB(), saveEquipToDB(), saveMobileToDB()]); } -// 모든 소프트웨어 DB 동기화 async function saveAllSoftwareToDB() { - await Promise.all([ - saveSubSwToDB(), - savePermSwToDB(), - saveCloudToDB(), - saveSwUsersToDB() - ]); + await Promise.all([saveSubSwToDB(), savePermSwToDB(), saveCloudToDB(), saveSwUsersToDB()]); } // --- App Initialization --- function initApp() { - console.log('🚀 ITAM Dedicated System Initializing...'); const mainContent = document.getElementById('main-content')!; if (!mainContent) return; const { closeAllModals } = initBaseModal(); - + + // 탭 변경 시 실행될 통합 렌더링 함수 + const handleTabChange = (tab: string) => { + if (tab === '대시보드') { + renderDashboard(mainContent); + } else { + renderSWTable(mainContent); + } + }; + try { - renderNavigation((tab) => { - if (tab === '대시보드') { - renderDashboard(mainContent); - } else { - renderSWTable(mainContent); + // 1. 네비게이션 렌더링 및 콜백 연결 + renderNavigation(handleTabChange); + + // 2. 각종 모달 및 가이드 초기화 + initHwModal(() => { saveAllHardwareToDB(); renderSWTable(mainContent); }, closeAllModals); + initSwModal(() => { saveAllSoftwareToDB(); renderSWTable(mainContent); }, closeAllModals); + initSwUserModal(() => { saveSwUsersToDB(); renderSWTable(mainContent); }, closeAllModals); + initDashboardDetailModal(); + initGuide(); + + // 4. DB 데이터 로드 및 초기 화면 렌더링 + loadMasterDataFromDB().then((success) => { + if (success) { + handleTabChange(state.activeSubTab); } }); - // 모달 초기화 - initHwModal(() => { saveAllHardwareToDB(); renderSWTable(mainContent); }, closeAllModals); - - initSwModal(() => { - saveAllSoftwareToDB(); - renderSWTable(mainContent); - }, closeAllModals); - - initSwUserModal(() => { - saveSwUsersToDB(); - renderSWTable(mainContent); - }, closeAllModals); - - initDashboardDetailModal(); - initGuide(); // 가이드 초기화 추가 } catch (e) { console.error('❌ Initialization failed:', e); } - // 초기 로드 시 대시보드 렌더링 - renderDashboard(mainContent); - - // DB에서 데이터 로드 후 화면 갱신 - loadMasterDataFromDB().then((success) => { - if (success) { - if (state.activeSubTab === '대시보드') renderDashboard(mainContent); - else renderSWTable(mainContent); - } - }); - // 버튼 이벤트 바인딩 document.getElementById('btn-download-template')?.addEventListener('click', () => downloadTemplate()); document.getElementById('btn-export-excel')?.addEventListener('click', () => exportToExcel(state.masterData)); @@ -112,46 +90,24 @@ function initApp() { if (file) { const data = await parseExcel(file); state.masterData = data; - await Promise.all([ - saveAllHardwareToDB(), - saveAllSoftwareToDB() - ]); - renderSWTable(mainContent); + await Promise.all([saveAllHardwareToDB(), saveAllSoftwareToDB()]); + handleTabChange(state.activeSubTab); } }); document.getElementById('btn-add-asset')?.addEventListener('click', () => { const tab = state.activeSubTab; const cat = state.activeCategory; - if (cat === 'hw') { - // 탭 명칭을 실제 유형명으로 매핑 - let defaultType = ''; - if (tab === '개인PC') defaultType = 'PC'; - else if (tab === '서버') defaultType = '서버'; - else if (tab === '스토리지') defaultType = '스토리지'; - else if (tab === '전산비품') defaultType = 'CPU'; - else if (tab === '모바일기기') defaultType = '모바일'; - - openHwModal({ - id: Math.random().toString(36).substring(2, 9), - type: defaultType, - 법인: '한맥', 자산코드: '', 명칭: '', 설치위치: '', MACaddress: '', HW사양: '', OS: '', 연락처: '', 담당부서: '' - } as any, 'add'); + let defaultType = (tab === '개인PC') ? 'PC' : (tab === '서버' ? '서버' : (tab === '스토리지' ? '스토리지' : (tab === '전산비품' ? 'CPU' : '모바일'))); + openHwModal({ id: Math.random().toString(36).substring(2, 9), type: defaultType, 법인: '한맥', 자산코드: '', 명칭: '', 설치위치: '', MACaddress: '', HW사양: '', OS: '', 연락처: '', 담당부서: '' } as any, 'add'); } else if (cat === 'sw') { - // 소프트웨어 대시보드 또는 개별 탭에서 추가 - let defaultType = tab; - if (tab === '대시보드') defaultType = '구독SW'; // SW는 기본 레이아웃을 위해 하나 지정하되 필드는 빈값 - - openSwModal({ - id: Math.random().toString(36).substring(2, 9), - type: defaultType, 제품명: '', 금액: '', 수량: 1, 계정명: '', 납품업체: '', 비고: '', 법인: '한맥' - } as any, 'add'); + openSwModal({ id: Math.random().toString(36).substring(2, 9), type: tab === '대시보드' ? '구독SW' : tab, 제품명: '', 금액: '', 수량: 1, 계정명: '', 납품업체: '', 비고: '', 법인: '한맥' } as any, 'add'); } }); createIcons({ - icons: { Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, History, RefreshCcw, BookOpen } + icons: { Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, History, RefreshCcw, BookOpen, Settings } }); } diff --git a/src/styles/common.css b/src/styles/common.css index 01ce326..56ec9af 100644 --- a/src/styles/common.css +++ b/src/styles/common.css @@ -1,7 +1,67 @@ :root { - --primary-color: #1E5149; - --primary-hover: #153c36; - --primary-light: #edf2f1; + /* --- System Colors (Added) --- */ + --color-red: #F21D0D; + --color-pink: #E8175E; + --color-magenta: #B92ED1; + --color-purple: #6D3DC2; + --color-navy: #4255bd; + --color-blue: #0D8DF2; + --color-cyan: #03AEFC; + --color-green: #4DB251; + --color-yellow: #FFBF00; + --color-orange: #FF9800; + --color-dahong: #FF3D00; + --color-brown: #A0705F; + --color-iron: #7F7F7F; + --color-steel: #688897; + + --color-red-light: #FEE9E7; + --color-pink-light: #FDE8EF; + --color-magenta-light: #F8EBFB; + --color-purple-light: #F1ECF9; + --color-navy-light: #EDEEF9; + --color-blue-light: #E7F4FE; + --color-cyan-light: #E6F7FF; + --color-green-light: #EEF8EE; + --color-yellow-light: #FFF9E6; + --color-orange-light: #FFF5E6; + --color-dahong-light: #FFECE6; + --color-brown-light: #F6F1EF; + --color-iron-light: #F3F3F3; + --color-steel-light: #F0F4F5; + + --color-red-medium: #FAA59E; + --color-pink-medium: #F6A2BF; + --color-magenta-medium: #E3ABEC; + --color-purple-medium: #C5B1E7; + --color-navy-medium: #B3BBE5; + --color-blue-medium: #9ED1FA; + --color-cyan-medium: #9ADFFE; + --color-green-medium: #B8E0B9; + --color-yellow-medium: #FFE599; + --color-orange-medium: #FFD699; + --color-dahong-medium: #FFB199; + --color-brown-medium: #D9C6BF; + --color-iron-medium: #CCCCCC; + --color-steel-medium: #C3CFD5; + + /* --- Primary Brand Levels --- */ + --primary-lv-0: #E9EEED; + --primary-lv-1: #D2DCDB; + --primary-lv-2: #A5B9B6; + --primary-lv-3: #789792; + --primary-lv-4: #4B746D; + --primary-lv-5: #35635C; + --primary-lv-6: #1E5149; + --primary-lv-7: #1B443D; + --primary-lv-8: #193833; + --primary-lv-9: #162A27; + + /* --- Legacy Aliases (Maintained for compatibility) --- */ + --primary-color: var(--primary-lv-6); + --primary-hover: var(--primary-lv-5); + --primary-light: var(--primary-lv-0); + --text-main: #111827; --text-muted: #6B7280; --border-color: #E5E7EB; @@ -9,7 +69,7 @@ --bg-light: #FAFAFA; --sidebar-bg: #ffffff; --white: #FFFFFF; - --danger: #dc2626; + --danger: var(--color-red); --dash-primary: #6cc020; --dash-light: #f2f9ec; @@ -22,14 +82,15 @@ box-sizing: border-box; margin: 0; padding: 0; + letter-spacing: -0.02em; + /* 모든 요소에 자간 규칙 일괄 적용 */ } body { - font-family: 'Pretendard Variable', Pretendard, sans-serif; + font-family: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, system-ui, Roboto, 'Helvetica Neue', 'Segoe UI', 'Apple SD Gothic Neo', 'Noto Sans KR', 'Malgun Gothic', sans-serif; color: var(--text-main); background-color: var(--bg-color); line-height: 1.5; - letter-spacing: -0.02em; font-size: 14px; overflow: hidden; } @@ -57,14 +118,32 @@ body { gap: 1.5rem; } +.brand { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.main-logo { + height: 34px; + width: auto; +} + .brand h1 { - font-size: 1.2rem; + font-size: 1.1rem; + /* 전체적으로 살짝 축소 */ font-weight: 800; color: var(--text-main); white-space: nowrap; - margin-right: 1rem; } -.brand h1 span { color: var(--primary-color); } + +.brand h1 .sub-title { + font-size: 0.85rem; + /* 영문 제목은 더 작게 */ + color: var(--primary-color); + font-weight: 600; + margin-left: 0.25rem; +} .integrated-nav { flex: 1; @@ -93,7 +172,7 @@ body { } .lnb-shelf { - display: none; + display: none; align-items: center; gap: 0.25rem; padding: 0 0.75rem; @@ -118,7 +197,11 @@ body { white-space: nowrap; } -.lnb-item:hover { color: var(--primary-color); background-color: var(--bg-color); } +.lnb-item:hover { + color: var(--primary-color); + background-color: var(--bg-color); +} + .lnb-item.active { color: var(--primary-color); background-color: var(--primary-light); @@ -126,12 +209,23 @@ body { } @keyframes fadeIn { - from { opacity: 0; transform: translateX(-5px); } - to { opacity: 1; transform: translateX(0); } + from { + opacity: 0; + transform: translateX(-5px); + } + + to { + opacity: 1; + transform: translateX(0); + } } /* --- Global Actions & Buttons --- */ -.header-actions { display: flex; gap: 0.3rem; align-items: center; } +.header-actions { + display: flex; + gap: 0.3rem; + align-items: center; +} .btn { display: inline-flex; @@ -145,30 +239,87 @@ body { cursor: pointer; height: 28px; line-height: 1; + white-space: nowrap; /* 텍스트 줄바꿈 방지 */ + flex-shrink: 0; /* 크기 찌그러짐 방지 */ } -.btn i, .btn svg { width: 12px !important; height: 12px !important; } +.btn i, +.btn svg { + width: 12px !important; + height: 12px !important; +} -.btn-primary { background-color: var(--primary-color); color: var(--white); border: 1px solid var(--primary-color); } -.btn-outline { background-color: transparent; color: var(--text-muted); border: 1px solid var(--border-color); } -.btn-danger { color: var(--danger) !important; border-color: var(--danger) !important; } +.btn-primary { + background-color: var(--primary-color); + color: var(--white); + border: 1px solid var(--primary-color); +} + +.btn-outline { + background-color: transparent; + color: var(--text-muted); + border: 1px solid var(--border-color); +} + +.btn-danger { + color: var(--danger) !important; + border-color: var(--danger) !important; +} /* --- Layout Frame --- */ .content-area { flex: 1; - padding: 2rem; - overflow-y: auto; + padding: 0 2rem; + /* 좌우 여백만 유지 */ + overflow: hidden; + /* 전체 스크롤 차단 */ + display: flex; + flex-direction: column; } .view-container { + flex: 1; width: 100%; display: flex; flex-direction: column; - gap: 1.5rem; + overflow: hidden; + /* 내부 스크롤을 유도하기 위해 설정 */ } -.hidden { display: none !important; } -.text-nowrap { white-space: nowrap; } +/* --- Footer --- */ +.main-footer { + height: 40px; + background-color: var(--white); + border-top: 1px solid var(--border-color); + display: flex; + align-items: center; + justify-content: flex-end; + padding: 0 1.5rem; + flex-shrink: 0; +} + +.main-footer p { + font-family: 'Pretendard Variable', Pretendard, sans-serif; + font-size: 0.75rem; + font-weight: 300; + line-height: 1.25rem; + letter-spacing: -0.0175rem; + color: #777777; + user-select: none; + pointer-events: all; + -webkit-user-drag: none; + margin: 0; + padding: 0; + box-sizing: border-box; +} + +.hidden { + display: none !important; +} + +.text-nowrap { + white-space: nowrap; +} /* --- Utility Styles --- */ .badge { @@ -178,8 +329,16 @@ body { font-weight: 700; white-space: nowrap; } -.badge-primary { background-color: var(--primary-color); color: white; } -.badge-muted { background-color: #9CA3AF; color: white; } + +.badge-primary { + background-color: var(--primary-color); + color: white; +} + +.badge-muted { + background-color: #9CA3AF; + color: white; +} .text-tag { color: var(--text-muted); @@ -190,4 +349,27 @@ body { background-color: var(--bg-light); } -.font-bold { font-weight: 700; } +.font-bold { + font-weight: 700; +} + +/* --- Responsive Design (Tablet & Mobile) --- */ +@media (max-width: 1200px) { + .header-container { gap: 0.75rem; padding: 0 1rem; } + .brand h1 { font-size: 1rem; } + .brand h1 .sub-title { font-size: 0.75rem; } +} + +@media (max-width: 992px) { + .main-header { height: auto; padding: 0.5rem 0; } + .header-container { flex-direction: column; align-items: flex-start; gap: 0.5rem; } + .integrated-nav { width: 100%; justify-content: flex-start; border-top: 1px solid var(--border-color); padding-top: 0.5rem; } + .header-actions { width: 100%; justify-content: flex-end; padding-top: 0.5rem; } + .content-area { padding: 0 1rem; } +} + +@media (max-width: 768px) { + .brand h1 .sub-title { display: none; } /* 아주 좁은 화면에선 영문명 숨김 */ + .header-actions .btn span { display: none; } /* 버튼 텍스트 숨기고 아이콘만 표시 */ + .header-actions .btn { padding: 0 0.5rem; } +} \ No newline at end of file diff --git a/src/styles/guide.css b/src/styles/guide.css index e2d40cf..73b0e13 100644 --- a/src/styles/guide.css +++ b/src/styles/guide.css @@ -1,112 +1,24 @@ -/* ITAM Guide Modal Styles */ -:root { - --guide-modal-width: 1060px; - --guide-modal-height: 92vh; - --guide-primary: #1E5149; - --guide-accent: #6cc020; -} +/* ITAM Guide Modal Styles - Updated to match common modal style */ -/* Floating Trigger Button - REMOVED (now in header) */ -.guide-trigger { - display: none; -} - -/* Modal Overlay */ -.guide-overlay { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - background-color: rgba(0, 0, 0, 0.5); - backdrop-filter: blur(4px); - z-index: 2000; - opacity: 0; - visibility: hidden; - transition: all 0.3s ease; - display: flex; - align-items: center; - justify-content: center; -} - -.guide-overlay.active { - opacity: 1; - visibility: visible; -} - -/* Guide Modal */ -.guide-modal { - width: var(--guide-modal-width); - max-width: 94vw; - height: var(--guide-modal-height); - background-color: #ffffff; - border-radius: 14px; - overflow: hidden; - box-shadow: 0 24px 60px rgba(0,0,0,0.3); - display: flex; - flex-direction: column; - transform: translateY(20px) scale(0.97); - opacity: 0; - transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); -} - -.guide-overlay.active .guide-modal { - transform: translateY(0) scale(1); - opacity: 1; -} - -/* Header */ -.guide-header { - padding: 1.1rem 1.5rem; +/* Tab Container (below header) */ +.guide-tabs-container { + background: #FAFAFA; border-bottom: 1px solid var(--border-color); - display: flex; - justify-content: space-between; - align-items: center; - background: linear-gradient(135deg, var(--guide-primary), #2a6d63); - color: white; - flex-shrink: 0; -} - -.guide-header h2 { - font-size: 1.15rem; - font-weight: 700; - display: flex; - align-items: center; - gap: 10px; - margin: 0; -} - -.btn-close-guide { - background: rgba(255, 255, 255, 0.12); - border: none; - color: white; - cursor: pointer; - width: 30px; - height: 30px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - transition: background 0.2s; -} - -.btn-close-guide:hover { - background: rgba(255, 255, 255, 0.3); -} - -/* ===== Tab Navigation ===== */ -.guide-tabs { - display: flex; - border-bottom: 1px solid var(--border-color); - background: #f8faf9; padding: 0 1.5rem; flex-shrink: 0; - gap: 2px; - overflow-x: auto; } +.guide-tabs { + display: flex; + gap: 2px; + overflow-x: auto; + scrollbar-width: none; +} + +.guide-tabs::-webkit-scrollbar { display: none; } + .guide-tab { - padding: 0.7rem 1rem; + padding: 0.75rem 1.25rem; font-size: 13px; font-weight: 600; color: var(--text-muted); @@ -114,37 +26,27 @@ border-bottom: 2px solid transparent; transition: all 0.2s ease; white-space: nowrap; - position: relative; - top: 1px; } .guide-tab:hover { - color: var(--guide-primary); + color: var(--primary-color); background: rgba(30, 81, 73, 0.04); } .guide-tab.active { - color: var(--guide-primary); - border-bottom-color: var(--guide-primary); + color: var(--primary-color); + border-bottom-color: var(--primary-color); background: white; } -/* ===== Content Area ===== */ +/* Content Area */ .guide-body { - flex: 1; - overflow-y: auto; - padding: 0; - scrollbar-width: none; /* Firefox */ - -ms-overflow-style: none; /* IE/Edge */ -} - -.guide-body::-webkit-scrollbar { - display: none; /* Chrome/Safari */ + padding-bottom: 2rem; } .guide-tab-panel { display: none; - padding: 1.5rem 2rem 2rem; + padding: 1.5rem 0; animation: guideFadeIn 0.3s ease; } @@ -157,12 +59,12 @@ to { opacity: 1; transform: translateY(0); } } -/* ===== Section Styles ===== */ +/* Section Styles */ .guide-section { display: flex; flex-direction: column; gap: 0.75rem; - margin-bottom: 1.5rem; + margin-bottom: 2rem; } .guide-section:last-child { @@ -171,84 +73,66 @@ .guide-section h3 { font-size: 1rem; - padding-bottom: 0.4rem; - border-bottom: 2px solid var(--guide-primary); - color: var(--guide-primary); + padding-bottom: 0.5rem; + border-bottom: 2px solid var(--primary-color); + color: var(--primary-color); margin: 0; display: flex; align-items: center; gap: 8px; } -.guide-section h4 { - font-size: 0.9rem; - color: var(--text-main); - margin: 0.6rem 0 0.2rem; - font-weight: 700; -} - .guide-text { font-size: 13px; - color: var(--text-muted); + color: var(--text-main); line-height: 1.7; margin: 0; } -.guide-text strong { - color: var(--text-main); -} - -/* ===== Flowchart ===== */ +/* Flowchart Styles */ .flow-container { display: flex; flex-direction: column; align-items: center; - gap: 0.5rem; - padding: 1.25rem; - background-color: #f8faf9; - border-radius: 12px; - border: 1px dashed #d0d7d5; + gap: 0.75rem; + padding: 1.5rem; + background-color: #f9fafb; + border-radius: 8px; + border: 1px solid var(--border-color); } .flow-row { display: flex; width: 100%; - gap: 0.75rem; - align-items: stretch; + gap: 1rem; + align-items: center; } .flow-step { flex: 1; background: white; - padding: 0.65rem 0.9rem; - border-radius: 8px; + padding: 1rem; + border-radius: 6px; border: 1px solid var(--border-color); display: flex; align-items: flex-start; - gap: 10px; - transition: transform 0.2s, box-shadow 0.2s; -} - -.flow-step:hover { - transform: translateY(-2px); - box-shadow: 0 4px 14px rgba(0,0,0,0.06); - border-color: var(--guide-primary); + gap: 12px; + box-shadow: 0 1px 3px rgba(0,0,0,0.05); } .flow-step .step-number { - width: 22px; - height: 22px; - min-width: 22px; + width: 24px; + height: 24px; + min-width: 24px; border-radius: 50%; - background-color: var(--guide-primary); + background-color: var(--primary-color); color: white; - font-size: 11px; + font-size: 12px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; - margin-top: 1px; } .flow-step .step-label { @@ -259,91 +143,46 @@ } .flow-step .step-desc { - font-size: 11.5px; + font-size: 12px; color: var(--text-muted); line-height: 1.5; - margin-top: 2px; -} - -.flow-arrow { - color: #b5c4c0; - width: 16px !important; - height: 16px !important; + margin-top: 4px; } .flow-arrow-right { - color: #b5c4c0; - width: 16px !important; - height: 16px !important; + color: var(--text-muted); display: flex; align-items: center; - flex-shrink: 0; } -/* ===== Info Table ===== */ +/* Info Table Style */ .guide-info-table { width: 100%; border-collapse: collapse; - font-size: 12.5px; - margin-top: 0.5rem; + font-size: 13px; } .guide-info-table th { - background: #f0f4f3; - color: var(--guide-primary); + background: #f8faf9; + color: var(--primary-color); font-weight: 700; - padding: 0.5rem 0.75rem; + padding: 0.75rem; text-align: left; - border-bottom: 2px solid var(--guide-primary); + border-bottom: 1px solid var(--border-color); } .guide-info-table td { - padding: 0.45rem 0.75rem; - border-bottom: 1px solid var(--border-color); + padding: 0.75rem; + border-bottom: 1px solid #f3f4f6; color: var(--text-main); - line-height: 1.5; } -.guide-info-table tr:hover td { - background: #f8faf9; -} - -/* ===== Tip Box ===== */ +/* Tip Box Style */ .guide-tip { - background: linear-gradient(135deg, #f0f9eb, #e8f5e0); - border-left: 4px solid var(--guide-accent); - border-radius: 0 8px 8px 0; - padding: 0.75rem 1rem; - font-size: 12.5px; - color: #2d5016; + background: var(--primary-light); + border-left: 4px solid var(--primary-color); + padding: 1rem; + font-size: 13px; + color: var(--primary-color); line-height: 1.6; } - -.guide-tip strong { - color: #1a3a0a; -} - -/* ===== Warning Box ===== */ -.guide-warn { - background: linear-gradient(135deg, #fff8ed, #fff3e0); - border-left: 4px solid #ff9800; - border-radius: 0 8px 8px 0; - padding: 0.75rem 1rem; - font-size: 12.5px; - color: #7a4a00; - line-height: 1.6; -} - -/* ===== Badge ===== */ -.guide-badge { - display: inline-block; - padding: 2px 8px; - border-radius: 4px; - font-size: 11px; - font-weight: 700; -} - -.guide-badge.green { background: #e6f4ea; color: #137333; } -.guide-badge.orange { background: #fff4e5; color: #b45309; } -.guide-badge.blue { background: #e8f0fe; color: #1a56db; } -.guide-badge.red { background: #fce8e6; color: #c5221f; } diff --git a/src/styles/table.css b/src/styles/table.css index a18f087..357d9ec 100644 --- a/src/styles/table.css +++ b/src/styles/table.css @@ -4,11 +4,10 @@ display: flex; flex-wrap: wrap; gap: 1.25rem; - background-color: var(--white); - padding: 1.5rem; - border: 1px solid var(--border-color); - border-radius: 8px; + padding: 1.5rem 0; /* 좌우 패딩 제거, 상하 여백 유지 */ + border-bottom: 1px solid var(--border-color); /* 하단 구분선만 남김 */ align-items: flex-end; + margin-bottom: 0.5rem; } .search-item { @@ -23,7 +22,7 @@ .search-item label { font-size: 11px; - font-weight: 800; + font-weight: 700; color: var(--text-muted); } @@ -35,70 +34,92 @@ border-radius: 4px; font-size: 14px; outline: none; + background-color: var(--white); } +/* 셀렉트 박스 화살표 여백 절대 고정 (수정 금지) */ .search-item select { - padding-right: 2.5rem; - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-9'/%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: right 0.75rem center; + padding-right: 2.5rem !important; + cursor: pointer; } +.search-item input:focus, +.search-item select:focus { + border-color: var(--primary-color); +} + +/* 필터 초기화 버튼 크기 조정 (입력창 높이 38px에 맞춤) */ .btn-reset { + margin-left: auto; height: 38px !important; - padding: 0 0.8rem !important; - font-size: 12px !important; - display: inline-flex !important; - align-items: center !important; - gap: 0.35rem !important; - border-radius: 4px !important; + color: var(--text-muted) !important; + padding: 0 1.2rem !important; + display: inline-flex; + align-items: center; + justify-content: center; } .table-container { + flex: 1; background-color: var(--white); border-top: 1px solid var(--border-color); - border-bottom: 1px solid var(--border-color); - border-left: none; - border-right: none; overflow: auto; - max-height: calc(100vh - 240px); } table { width: 100%; border-collapse: collapse; + table-layout: auto; } th, td { - padding: 1rem 1.5rem; - border-bottom: 1px solid var(--border-color); - text-align: left; + padding: 0.8rem 1.2rem; + border-bottom: 1px solid #F3F4F6; + text-align: left; /* 기본은 좌측 정렬 */ white-space: nowrap; } th { background-color: #FAFAFA; - font-weight: 700; + font-size: 13px; + font-weight: 600; color: var(--text-muted); - font-size: 12px; position: sticky; top: 0; z-index: 10; box-shadow: inset 0 -1px 0 var(--border-color); - text-transform: uppercase; + text-transform: none; } td { - font-size: 14px; + font-size: 13px; + color: var(--text-main); + font-weight: 400; } tbody tr:hover { background-color: #F9FAFB; } -.btn-sm { - padding: 0.25rem 0.5rem; - font-size: 11px; - height: 24px; +/* 정렬 클래스 강제 적용 */ +.text-center { text-align: center !important; } +.text-right { text-align: right !important; } +.text-left { text-align: left !important; } + +.btn-icon { + padding: 0.25rem; + border: none; + background: none; + cursor: pointer; + color: var(--text-muted); + transition: color 0.2s; +} + +.btn-icon:hover { + color: var(--primary-color); +} + +.btn-icon svg { + width: 16px; + height: 16px; } diff --git a/src/views/List/CloudListView.ts b/src/views/List/CloudListView.ts index 8efdc1f..ce1c30e 100644 --- a/src/views/List/CloudListView.ts +++ b/src/views/List/CloudListView.ts @@ -1,20 +1,24 @@ import { state } from '../../core/state'; import { openSwModal } from '../../components/Modal/SWModal'; -import { createIcons, Cloud, CreditCard, DollarSign } from 'lucide'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; +import { createIcons, Cloud, CreditCard, DollarSign, RefreshCcw } from 'lucide'; +/** + * 클라우드(운영 서비스) 자산 목록 뷰 + * 라인 정렬 보정 및 헤더 통일 + */ export function renderCloudList(container: HTMLElement) { - // DB에서 직접 로드된 전용 배열을 사용하여 데이터 소스를 일원화함 const getFullList = () => state.masterData.cloud || []; const filterBar = document.createElement('div'); filterBar.className = 'search-bar'; filterBar.innerHTML = `
- +
- +
`; container.appendChild(filterBar); @@ -33,16 +37,16 @@ export function renderCloudList(container: HTMLElement) { table.innerHTML = ` - No. - 플랫폼명 - 법인 - 담당부서 - 진행 프로젝트(사용용도) - 계정명(관리자) - 결제수단 - 결제일 - 당월 청구액 - 비고 + No. + ${ASSET_SCHEMA.PLATFORM.ui} + ${ASSET_SCHEMA.CORP.ui} + 담당부서 + 용도(프로젝트) + ${ASSET_SCHEMA.ACCOUNT.ui} + ${ASSET_SCHEMA.PAY_METHOD.ui} + ${ASSET_SCHEMA.PAY_DAY.ui} + ${ASSET_SCHEMA.BILLING.ui} + ${ASSET_SCHEMA.REMARKS.ui} @@ -61,16 +65,16 @@ export function renderCloudList(container: HTMLElement) { const filtered = getFullList().filter(asset => { const kwMatch = !keyword || - (asset.제품명 || '').toLowerCase().includes(keyword) || + (asset[ASSET_SCHEMA.PRODUCT.key] || '').toLowerCase().includes(keyword) || (asset.부서 || '').toLowerCase().includes(keyword) || - (asset.계정명 || '').toLowerCase().includes(keyword); - const payMatch = !payment || asset.결제수단 === payment; + (asset[ASSET_SCHEMA.ACCOUNT.key] || '').toLowerCase().includes(keyword); + const payMatch = !payment || asset[ASSET_SCHEMA.PAY_METHOD.key] === payment; return kwMatch && payMatch; }); tbody.innerHTML = ''; if (filtered.length === 0) { - tbody.innerHTML = '등록된 클라우드 서비스가 없습니다.'; + tbody.innerHTML = `${UI_TEXT.MESSAGES.NO_DATA}`; return; } @@ -78,29 +82,30 @@ export function renderCloudList(container: HTMLElement) { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; - const paymentBadge = asset.결제수단 === '법인카드' - ? '법인카드 (' + (asset.연결카드번호||'미상') + ')' - : (asset.결제수단 === '인보이스' + const payMethod = asset[ASSET_SCHEMA.PAY_METHOD.key]; + const paymentBadge = payMethod === '법인카드' + ? `법인카드` + : (payMethod === '인보이스' ? '인보이스' : '미설정'); tr.innerHTML = ` - ${idx+1} - ${asset.플랫폼명||'미지정'} - ${asset.법인||''} - ${asset.부서||''} - ${asset.제품명||''} - ${asset.계정명||''} - ${paymentBadge} - ${asset.결제일 ? asset.결제일 + '일' : ''} - ₩ ${asset.당월청구액 ? Number(asset.당월청구액).toLocaleString() : '0'} - ${asset.비고||''} + ${idx+1} + ${asset[ASSET_SCHEMA.PLATFORM.key]||'미지정'} + ${asset[ASSET_SCHEMA.CORP.key]||''} + ${asset.부서||''} + ${asset[ASSET_SCHEMA.PRODUCT.key]||''} + ${asset[ASSET_SCHEMA.ACCOUNT.key]||''} + ${paymentBadge} + ${asset[ASSET_SCHEMA.PAY_DAY.key] ? asset[ASSET_SCHEMA.PAY_DAY.key] + '일' : ''} + ₩ ${asset[ASSET_SCHEMA.BILLING.key] ? Number(asset[ASSET_SCHEMA.BILLING.key]).toLocaleString() : '0'} + ${asset[ASSET_SCHEMA.REMARKS.key]||''} `; tr.addEventListener('click', () => openSwModal(asset, 'view')); tbody.appendChild(tr); }); - createIcons({ icons: { Cloud, CreditCard, DollarSign } }); + createIcons({ icons: { Cloud, CreditCard, DollarSign, RefreshCcw } }); }; document.getElementById('filter-keyword')?.addEventListener('input', updateTable); diff --git a/src/views/List/EquipmentListView.ts b/src/views/List/EquipmentListView.ts index 37bd4b0..f8c8f6e 100644 --- a/src/views/List/EquipmentListView.ts +++ b/src/views/List/EquipmentListView.ts @@ -1,29 +1,31 @@ import { state } from '../../core/state'; import { openHwModal } from '../../components/Modal/HWModal'; -import { formatInline, sortAssets } from '../../core/utils'; +import { formatInline, createBadge, sortAssets } from '../../core/utils'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; import { createIcons, RefreshCcw } from 'lucide'; +/** + * 전산비품 자산 목록 뷰 + * 라인 정렬 보정 및 헤더 통일 + */ export function renderEquipmentList(container: HTMLElement) { const fullList = sortAssets(state.masterData.equip); const filterBar = document.createElement('div'); filterBar.className = 'search-bar'; - const corps = Array.from(new Set(fullList.map(a => a.법인))).filter(Boolean).sort(); + const corps = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.CORP.key]))).filter(Boolean).sort(); filterBar.innerHTML = `
- +
- +
- `; container.appendChild(filterBar); @@ -34,16 +36,16 @@ export function renderEquipmentList(container: HTMLElement) { table.innerHTML = ` - No. - 상태 - 구매법인 - 유형 - 자산번호 - 모델명 - 보관위치 - 관리자 - 구매연월 - 금액 + No. + ${ASSET_SCHEMA.STATUS.ui} + ${ASSET_SCHEMA.CORP.ui} + 유형 + ${ASSET_SCHEMA.ASSET_CODE.ui} + ${ASSET_SCHEMA.MODEL.ui} + ${ASSET_SCHEMA.STORE_LOC.ui} + 담당자(정/부) + ${ASSET_SCHEMA.PURCHASE_YM.ui} + ${ASSET_SCHEMA.PRICE.ui} @@ -61,14 +63,17 @@ export function renderEquipmentList(container: HTMLElement) { const corp = corpSelect ? corpSelect.value : ''; const filtered = fullList.filter(asset => { - const matchKeyword = !keyword || String(asset.자산코드||'').toLowerCase().includes(keyword) || String(asset.모델명||'').toLowerCase().includes(keyword) || String(asset.현사용조직||'').toLowerCase().includes(keyword); - const matchCorp = !corp || asset.법인 === corp; + const matchKeyword = !keyword || + String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.MODEL.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.MANAGER_MAIN.key]||'').toLowerCase().includes(keyword); + const matchCorp = !corp || asset[ASSET_SCHEMA.CORP.key] === corp; return matchKeyword && matchCorp; }); tbody.innerHTML = ''; if (filtered.length === 0) { - tbody.innerHTML = `검색 결과가 없습니다.`; + tbody.innerHTML = `${UI_TEXT.MESSAGES.NO_DATA}`; return; } @@ -76,32 +81,34 @@ export function renderEquipmentList(container: HTMLElement) { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; - const statusColors: Record = { - '대여중': '#3b82f6', - '보관중': '#1E5149', - '수리중': '#ef4444', - '기타': '#6b7280' - }; - const statusColor = statusColors[asset.현재상태 || '보관중'] || '#6b7280'; - const statusBadge = `${asset.현재상태 || '보관중'}`; + const statusColors: Record = { '대여중': 'primary', '보관중': 'success', '수리중': 'danger', '기타': 'muted' }; + const statusValue = asset[ASSET_SCHEMA.STATUS.key] || '보관중'; + const statusType = statusColors[statusValue] || 'muted'; + const statusBadge = `${statusValue}`; + + const mainManager = asset[ASSET_SCHEMA.MANAGER_MAIN.key] || ''; + const subManager = asset[ASSET_SCHEMA.MANAGER_SUB.key] || ''; + const managerHtml = [ + mainManager ? `${createBadge('정', 'primary')} ${mainManager}` : '', + subManager ? `${createBadge('부', 'muted')} ${subManager}` : '' + ].filter(v => v !== '').join(' / '); tr.innerHTML = ` - ${idx + 1} - ${statusBadge} - ${asset.법인} - ${asset.type} - ${asset.자산코드 || '-'} - ${formatInline(asset.모델명 || asset.명칭)} - ${asset.보관위치 || '-'} - ${formatInline(asset.담당자_정 || asset.관리자)} - ${asset.구매일 || ''} - ${asset.금액 || '0'} + ${idx + 1} + ${statusBadge} + ${asset[ASSET_SCHEMA.CORP.key]} + ${asset[ASSET_SCHEMA.TYPE.key]} + ${asset[ASSET_SCHEMA.ASSET_CODE.key] || '-'} + ${formatInline(asset[ASSET_SCHEMA.MODEL.key] || asset.명칭)} + ${asset[ASSET_SCHEMA.STORE_LOC.key] || '-'} + ${managerHtml || '-'} + ${asset[ASSET_SCHEMA.PURCHASE_YM.key] || ''} + ${Number(asset[ASSET_SCHEMA.PRICE.key]||0).toLocaleString()} `; - tr.addEventListener('click', (e) => { - if (!(e.target as HTMLElement).closest('button')) openHwModal(asset, 'view'); - }); + tr.addEventListener('click', () => openHwModal(asset, 'view')); tbody.appendChild(tr); }); + createIcons({ icons: { RefreshCcw } }); }; document.getElementById('filter-keyword')?.addEventListener('input', updateTable); diff --git a/src/views/List/MobileListView.ts b/src/views/List/MobileListView.ts index 4ab2bac..8a9c7d5 100644 --- a/src/views/List/MobileListView.ts +++ b/src/views/List/MobileListView.ts @@ -1,29 +1,31 @@ import { state } from '../../core/state'; import { openHwModal } from '../../components/Modal/HWModal'; -import { formatInline, sortAssets } from '../../core/utils'; +import { formatInline, createBadge, sortAssets } from '../../core/utils'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; import { createIcons, RefreshCcw } from 'lucide'; +/** + * 모바일기기 자산 목록 뷰 + * 라인 정렬 보정 및 헤더 통일 + */ export function renderMobileList(container: HTMLElement) { const fullList = sortAssets(state.masterData.mobile); const filterBar = document.createElement('div'); filterBar.className = 'search-bar'; - const corps = Array.from(new Set(fullList.map(a => a.법인))).filter(Boolean).sort(); + const corps = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.CORP.key]))).filter(Boolean).sort(); filterBar.innerHTML = `
- +
- +
- `; container.appendChild(filterBar); @@ -34,21 +36,20 @@ export function renderMobileList(container: HTMLElement) { table.innerHTML = ` - No. - 상태 - 구매법인 - 자산코드 - 명칭 - 보관위치 - 관리자 - 구매연월 - 금액 + No. + ${ASSET_SCHEMA.STATUS.ui} + ${ASSET_SCHEMA.CORP.ui} + ${ASSET_SCHEMA.ASSET_CODE.ui} + ${ASSET_SCHEMA.MODEL.ui} + ${ASSET_SCHEMA.STORE_LOC.ui} + 담당자(정/부) + ${ASSET_SCHEMA.PURCHASE_YM.ui} + ${ASSET_SCHEMA.PRICE.ui} `; - tableWrapper.appendChild(table); container.appendChild(tableWrapper); const tbody = table.querySelector('tbody')!; @@ -61,14 +62,17 @@ export function renderMobileList(container: HTMLElement) { const corp = corpSelect ? corpSelect.value : ''; const filtered = fullList.filter(asset => { - const matchKeyword = !keyword || String(asset.자산코드||'').toLowerCase().includes(keyword) || String(asset.모델명||'').toLowerCase().includes(keyword) || String(asset.현사용조직||'').toLowerCase().includes(keyword); - const matchCorp = !corp || asset.법인 === corp; + const matchKeyword = !keyword || + String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.MODEL.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.MANAGER_MAIN.key]||'').toLowerCase().includes(keyword); + const matchCorp = !corp || asset[ASSET_SCHEMA.CORP.key] === corp; return matchKeyword && matchCorp; }); tbody.innerHTML = ''; if (filtered.length === 0) { - tbody.innerHTML = `검색 결과가 없습니다.`; + tbody.innerHTML = `${UI_TEXT.MESSAGES.NO_DATA}`; return; } @@ -76,31 +80,33 @@ export function renderMobileList(container: HTMLElement) { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; - const statusColors: Record = { - '대여중': '#3b82f6', - '보관중': '#1E5149', - '수리중': '#ef4444', - '기타': '#6b7280' - }; - const statusColor = statusColors[asset.현재상태 || '보관중'] || '#6b7280'; - const statusBadge = `${asset.현재상태 || '보관중'}`; + const statusColors: Record = { '대여중': 'primary', '보관중': 'success', '수리중': 'danger', '기타': 'muted' }; + const statusValue = asset[ASSET_SCHEMA.STATUS.key] || '보관중'; + const statusType = statusColors[statusValue] || 'muted'; + const statusBadge = `${statusValue}`; + + const mainManager = asset[ASSET_SCHEMA.MANAGER_MAIN.key] || ''; + const subManager = asset[ASSET_SCHEMA.MANAGER_SUB.key] || ''; + const managerHtml = [ + mainManager ? `${createBadge('정', 'primary')} ${mainManager}` : '', + subManager ? `${createBadge('부', 'muted')} ${subManager}` : '' + ].filter(v => v !== '').join(' / '); tr.innerHTML = ` - ${idx + 1} - ${statusBadge} - ${asset.법인} - ${asset.자산코드 || '-'} - ${formatInline(asset.명칭 || asset.모델명)} - ${asset.보관위치 || '-'} - ${formatInline(asset.관리자 || asset.담당자_정)} - ${asset.구매일 || ''} - ${asset.금액 || '0'} + ${idx + 1} + ${statusBadge} + ${asset[ASSET_SCHEMA.CORP.key]} + ${asset[ASSET_SCHEMA.ASSET_CODE.key] || '-'} + ${formatInline(asset[ASSET_SCHEMA.MODEL.key] || asset.명칭)} + ${asset[ASSET_SCHEMA.STORE_LOC.key] || '-'} + ${managerHtml || '-'} + ${asset[ASSET_SCHEMA.PURCHASE_YM.key] || ''} + ${Number(asset[ASSET_SCHEMA.PRICE.key]||0).toLocaleString()} `; - tr.addEventListener('click', (e) => { - if (!(e.target as HTMLElement).closest('button')) openHwModal(asset, 'view'); - }); + tr.addEventListener('click', () => openHwModal(asset, 'view')); tbody.appendChild(tr); }); + createIcons({ icons: { RefreshCcw } }); }; document.getElementById('filter-keyword')?.addEventListener('input', updateTable); @@ -109,8 +115,7 @@ export function renderMobileList(container: HTMLElement) { (document.getElementById('filter-keyword') as HTMLInputElement).value = ''; (document.getElementById('filter-corp') as HTMLSelectElement).value = ''; updateTable(); - }); - - updateTable(); - } + }); + updateTable(); +} diff --git a/src/views/List/PcListView.ts b/src/views/List/PcListView.ts index 4b97b64..59d2cb0 100644 --- a/src/views/List/PcListView.ts +++ b/src/views/List/PcListView.ts @@ -1,26 +1,32 @@ import { state } from '../../core/state'; import { openHwModal } from '../../components/Modal/HWModal'; -import { formatInline, sortAssets } from '../../core/utils'; +import { formatInline, createBadge, sortAssets } from '../../core/utils'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; import { createIcons, Paperclip, RefreshCcw } from 'lucide'; +/** + * PC 자산 목록 뷰 + * 담당자(부) 추가 및 정렬 보정 + */ export function renderPcList(container: HTMLElement) { const fullList = sortAssets(state.masterData.pc); const filterBar = document.createElement('div'); filterBar.className = 'search-bar'; - const corps = Array.from(new Set(fullList.map(a => a.법인))).filter(Boolean).sort(); + + const corps = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.CORP.key]))).filter(Boolean).sort(); filterBar.innerHTML = `
- +
- +
`; container.appendChild(filterBar); @@ -28,11 +34,30 @@ export function renderPcList(container: HTMLElement) { const tableWrapper = document.createElement('div'); tableWrapper.className = 'table-container'; const table = document.createElement('table'); - table.innerHTML = `No구매법인현 사용조직자산코드사용자위치CPURAMStorage구매연월금액품의서관리`; + table.innerHTML = ` + + + No + ${ASSET_SCHEMA.CORP.ui} + ${ASSET_SCHEMA.ORG.ui} + ${ASSET_SCHEMA.ASSET_CODE.ui} + ${ASSET_SCHEMA.USER.ui} + ${ASSET_SCHEMA.LOCATION.ui} + 담당자(정/부) + ${ASSET_SCHEMA.MAINBOARD.ui} + ${ASSET_SCHEMA.CPU.ui} + ${ASSET_SCHEMA.RAM.ui} + Storage + ${ASSET_SCHEMA.PURCHASE_YM.ui} + ${ASSET_SCHEMA.PRICE.ui} + ${ASSET_SCHEMA.DOC_NAME.ui} + + + + `; tableWrapper.appendChild(table); container.appendChild(tableWrapper); - const tbody = table.querySelector('tbody')!; const updateTable = () => { @@ -43,41 +68,54 @@ export function renderPcList(container: HTMLElement) { const corp = corpSelect ? corpSelect.value : ''; const filtered = fullList.filter(asset => { - const matchKeyword = !keyword || String(asset.자산코드||'').toLowerCase().includes(keyword) || String(asset.사용자||'').toLowerCase().includes(keyword) || String(asset.현사용조직||'').toLowerCase().includes(keyword); - const matchCorp = !corp || asset.법인 === corp; + const matchKeyword = !keyword || + String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.USER.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.ORG.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.MANAGER_MAIN.key]||'').toLowerCase().includes(keyword); + const matchCorp = !corp || asset[ASSET_SCHEMA.CORP.key] === corp; return matchKeyword && matchCorp; }); tbody.innerHTML = ''; if (filtered.length === 0) { - tbody.innerHTML = `검색 결과가 없습니다.`; + tbody.innerHTML = `${UI_TEXT.MESSAGES.NO_DATA}`; return; } filtered.forEach((asset, idx) => { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; - const storage = [asset.SSD1, asset.SSD2, asset.HDD1].filter(v => v).join(' / '); + const storage = [asset[ASSET_SCHEMA.STORAGE1.key], asset[ASSET_SCHEMA.STORAGE2.key]].filter(v => v).join(' / '); + + const mainManager = asset[ASSET_SCHEMA.MANAGER_MAIN.key] || ''; + const subManager = asset[ASSET_SCHEMA.MANAGER_SUB.key] || ''; + const managerHtml = [ + mainManager ? `${createBadge('정', 'primary')} ${mainManager}` : '', + subManager ? `${createBadge('부', 'muted')} ${subManager}` : '' + ].filter(v => v !== '').join(' / '); + tr.innerHTML = ` - ${idx+1} - ${asset.법인} - ${asset.현사용조직||''} - ${asset.자산코드} - ${asset.사용자||''} - ${asset.위치||''} - ${asset.CPU||''} - ${asset.RAM||''} - ${formatInline(storage)} - ${asset.구매연월 || asset.구매일 || ''} - ${asset.금액||''} - ${asset.품의서명 ? '' : '-'} - + ${idx+1} + ${asset[ASSET_SCHEMA.CORP.key]} + ${asset[ASSET_SCHEMA.ORG.key]||'-'} + ${asset[ASSET_SCHEMA.ASSET_CODE.key]} + ${asset[ASSET_SCHEMA.USER.key]||''} + ${asset[ASSET_SCHEMA.LOCATION.key]||''} + ${managerHtml || '-'} + ${asset[ASSET_SCHEMA.MAINBOARD.key]||'-'} + ${asset[ASSET_SCHEMA.CPU.key]||''} + ${asset[ASSET_SCHEMA.RAM.key]||''} + ${formatInline(storage)} + ${asset[ASSET_SCHEMA.PURCHASE_YM.key] || ''} + ${Number(asset[ASSET_SCHEMA.PRICE.key]||0).toLocaleString()} + ${asset[ASSET_SCHEMA.DOC_NAME.key] ? '' : '-'} `; - tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset, 'view'); }); + tr.addEventListener('click', () => openHwModal(asset, 'view')); tbody.appendChild(tr); }); - createIcons({ icons: { Paperclip } }); + createIcons({ icons: { Paperclip, RefreshCcw } }); }; document.getElementById('filter-keyword')?.addEventListener('input', updateTable); diff --git a/src/views/List/ServerListView.ts b/src/views/List/ServerListView.ts index d374f48..b1fa44c 100644 --- a/src/views/List/ServerListView.ts +++ b/src/views/List/ServerListView.ts @@ -1,31 +1,37 @@ import { state } from '../../core/state'; import { openHwModal } from '../../components/Modal/HWModal'; import { formatInline, createBadge, sortAssets } from '../../core/utils'; -import { createIcons, RefreshCcw, Edit2 } from 'lucide'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; +import { createIcons, RefreshCcw } from 'lucide'; +/** + * 서버 자산 목록 뷰 + * 라인 정렬 보정 및 헤더 통일 + */ export function renderServerList(container: HTMLElement) { const fullList = sortAssets(state.masterData.server); const filterBar = document.createElement('div'); filterBar.className = 'search-bar'; - const corps = Array.from(new Set(fullList.map(a => a.법인))).filter(Boolean).sort(); - const orgUnits = Array.from(new Set(fullList.map(a => a.현사용조직))).filter(Boolean).sort(); + + 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(); filterBar.innerHTML = `
- +
- +
- +
`; container.appendChild(filterBar); @@ -33,7 +39,21 @@ export function renderServerList(container: HTMLElement) { const tableWrapper = document.createElement('div'); tableWrapper.className = 'table-container'; const table = document.createElement('table'); - table.innerHTML = `No구매법인현 사용조직자산번호용도상세설치위치담당자관리`; + table.innerHTML = ` + + + No + ${ASSET_SCHEMA.CORP.ui} + ${ASSET_SCHEMA.ORG.ui} + ${ASSET_SCHEMA.ASSET_CODE.ui} + 용도 + 상세 + ${ASSET_SCHEMA.LOCATION.ui} + 담당자(정/부) + + + + `; tableWrapper.appendChild(table); container.appendChild(tableWrapper); @@ -49,15 +69,18 @@ export function renderServerList(container: HTMLElement) { const orgUnit = orgSelect ? orgSelect.value : ''; const filtered = fullList.filter(asset => { - const matchKeyword = !keyword || String(asset.자산코드||'').toLowerCase().includes(keyword) || String(asset.현사용조직||'').toLowerCase().includes(keyword) || String(asset.모델명||'').toLowerCase().includes(keyword); - const matchCorp = !corp || asset.법인 === corp; - const matchOrg = !orgUnit || asset.현사용조직 === orgUnit; + const matchKeyword = !keyword || + String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.ORG.key]||'').toLowerCase().includes(keyword) || + String(asset[ASSET_SCHEMA.MODEL.key]||'').toLowerCase().includes(keyword); + const matchCorp = !corp || asset[ASSET_SCHEMA.CORP.key] === corp; + const matchOrg = !orgUnit || asset[ASSET_SCHEMA.ORG.key] === orgUnit; return matchKeyword && matchCorp && matchOrg; }); tbody.innerHTML = ''; if (filtered.length === 0) { - tbody.innerHTML = `검색 결과가 없습니다.`; + tbody.innerHTML = `${UI_TEXT.MESSAGES.NO_DATA}`; return; } @@ -65,27 +88,24 @@ export function renderServerList(container: HTMLElement) { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; - const mainManager = asset.담당자_정 || ''; - const subManager = asset.담당자_부 || ''; + const mainManager = asset[ASSET_SCHEMA.MANAGER_MAIN.key] || ''; + const subManager = asset[ASSET_SCHEMA.MANAGER_SUB.key] || ''; const managerHtml = [ mainManager ? `${createBadge('정', 'primary')} ${mainManager}` : '', subManager ? `${createBadge('부', 'muted')} ${subManager}` : '' ].filter(v => v !== '').join(' / '); tr.innerHTML = ` - ${idx+1} - ${asset.법인} - ${asset.현사용조직||'-'} - ${asset.자산코드} + ${idx+1} + ${asset[ASSET_SCHEMA.CORP.key]} + ${asset[ASSET_SCHEMA.ORG.key]||'-'} + ${asset[ASSET_SCHEMA.ASSET_CODE.key]} ${formatInline(asset.용도)} ${formatInline(asset.상세)} - ${formatInline(asset.위치)} - ${managerHtml} - - - + ${formatInline(asset[ASSET_SCHEMA.LOCATION.key])} + ${managerHtml || '-'} `; - tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset, 'view'); }); + tr.addEventListener('click', () => openHwModal(asset, 'view')); tbody.appendChild(tr); }); }; @@ -101,5 +121,5 @@ export function renderServerList(container: HTMLElement) { }); updateTable(); - createIcons({ icons: { RefreshCcw, Edit2 } }); + createIcons({ icons: { RefreshCcw } }); } diff --git a/src/views/List/StorageListView.ts b/src/views/List/StorageListView.ts index 0c922b0..405fe09 100644 --- a/src/views/List/StorageListView.ts +++ b/src/views/List/StorageListView.ts @@ -1,31 +1,37 @@ import { state } from '../../core/state'; import { openHwModal } from '../../components/Modal/HWModal'; import { formatInline, createBadge, sortAssets } from '../../core/utils'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; import { createIcons, RefreshCcw } from 'lucide'; +/** + * 스토리지 자산 목록 뷰 + * 라인 정렬 보정 및 헤더 통일 + */ export function renderStorageList(container: HTMLElement) { const fullList = sortAssets(state.masterData.storage); const filterBar = document.createElement('div'); filterBar.className = 'search-bar'; - const corps = Array.from(new Set(fullList.map(a => a.법인))).filter(Boolean).sort(); - const orgUnits = Array.from(new Set(fullList.map(a => a.현사용조직))).filter(Boolean).sort(); + + 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(); filterBar.innerHTML = `
- +
- +
- +
`; container.appendChild(filterBar); @@ -33,7 +39,21 @@ export function renderStorageList(container: HTMLElement) { const tableWrapper = document.createElement('div'); tableWrapper.className = 'table-container'; const table = document.createElement('table'); - table.innerHTML = `No구매법인현 사용조직자산번호용도상세설치위치담당자모델명Storage관리`; + table.innerHTML = ` + + + No + ${ASSET_SCHEMA.CORP.ui} + ${ASSET_SCHEMA.ORG.ui} + ${ASSET_SCHEMA.ASSET_CODE.ui} + 용도 + 상세 + ${ASSET_SCHEMA.LOCATION.ui} + 담당자(정/부) + + + + `; tableWrapper.appendChild(table); container.appendChild(tableWrapper); @@ -49,15 +69,17 @@ export function renderStorageList(container: HTMLElement) { const orgUnit = orgSelect ? orgSelect.value : ''; const filtered = fullList.filter(asset => { - const matchKeyword = !keyword || String(asset.자산코드||'').toLowerCase().includes(keyword) || String(asset.현사용조직||'').toLowerCase().includes(keyword) || String(asset.모델명||'').toLowerCase().includes(keyword); - const matchCorp = !corp || asset.법인 === corp; - const matchOrg = !orgUnit || asset.현사용조직 === orgUnit; + 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; return matchKeyword && matchCorp && matchOrg; }); tbody.innerHTML = ''; if (filtered.length === 0) { - tbody.innerHTML = `검색 결과가 없습니다.`; + tbody.innerHTML = `${UI_TEXT.MESSAGES.NO_DATA}`; return; } @@ -65,26 +87,24 @@ export function renderStorageList(container: HTMLElement) { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; - const mainManager = asset.담당자_정 || asset.관리자 || ''; - const subManager = asset.담당자_부 || ''; - const managerHtml = [mainManager ? `${createBadge('정', '#1E5149')} ${mainManager}` : '', subManager ? `${createBadge('부', '#9CA3AF')} ${subManager}` : ''].filter(v => v !== '').join(' / '); + const mainManager = asset[ASSET_SCHEMA.MANAGER_MAIN.key] || ''; + const subManager = asset[ASSET_SCHEMA.MANAGER_SUB.key] || ''; + const managerHtml = [ + mainManager ? `${createBadge('정', 'primary')} ${mainManager}` : '', + subManager ? `${createBadge('부', 'muted')} ${subManager}` : '' + ].filter(v => v !== '').join(' / '); - const storage = [asset.SSD1, asset.SSD2, asset.용량].filter(v => v).join(' / '); - tr.innerHTML = ` - ${idx+1} - ${asset.법인} - ${asset.현사용조직||''} - ${asset.자산코드} + ${idx+1} + ${asset[ASSET_SCHEMA.CORP.key]} + ${asset[ASSET_SCHEMA.ORG.key]||'-'} + ${asset[ASSET_SCHEMA.ASSET_CODE.key]} ${formatInline(asset.용도)} ${formatInline(asset.상세)} - ${formatInline(asset.위치)} - ${managerHtml} - ${asset.모델명||''} - ${formatInline(storage)} - + ${formatInline(asset[ASSET_SCHEMA.LOCATION.key])} + ${managerHtml || '-'} `; - tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset, 'view'); }); + tr.addEventListener('click', () => openHwModal(asset, 'view')); tbody.appendChild(tr); }); }; @@ -100,4 +120,5 @@ export function renderStorageList(container: HTMLElement) { }); updateTable(); + createIcons({ icons: { RefreshCcw } }); } diff --git a/src/views/List/SwListView.ts b/src/views/List/SwListView.ts index 41c1a81..abd3a9a 100644 --- a/src/views/List/SwListView.ts +++ b/src/views/List/SwListView.ts @@ -1,11 +1,14 @@ import { state } from '../../core/state'; import { openSwModal } from '../../components/Modal/SWModal'; -import { openSwUserModal } from '../../components/Modal/SWUserModal'; import { sortAssets } from '../../core/utils'; import { CORP_LIST } from '../../components/Modal/SharedData'; import { generateOptionsHTML } from '../../components/Modal/ModalUtils'; -import { createIcons, Edit2, Users, RefreshCcw } from 'lucide'; +import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; +import { createIcons, RefreshCcw } from 'lucide'; +/** + * 소프트웨어(구독/영구) 자산 목록 뷰 + */ export function renderSwList(container: HTMLElement) { const isSub = state.activeSubTab === '구독SW'; const fullList = sortAssets(isSub ? state.masterData.subSw : state.masterData.permSw); @@ -14,7 +17,7 @@ export function renderSwList(container: HTMLElement) { filterBar.className = 'search-bar'; filterBar.innerHTML = `
- +
@@ -28,11 +31,11 @@ export function renderSwList(container: HTMLElement) {
- +
`; container.appendChild(filterBar); @@ -46,15 +49,14 @@ export function renderSwList(container: HTMLElement) { No. 상태 분야 - 구매법인 + ${ASSET_SCHEMA.CORP.ui} 부서 - 제품명 - 구매연월 - ${isSub ? '구독일' : ''} - 금액 - 수량 + ${ASSET_SCHEMA.PRODUCT.ui} + ${ASSET_SCHEMA.PURCHASE_YM.ui} + ${isSub ? `${ASSET_SCHEMA.EXPIRY.ui}` : ''} + ${ASSET_SCHEMA.PRICE.ui} + ${ASSET_SCHEMA.QTY.ui} 사용가능 - 관리 @@ -74,28 +76,28 @@ export function renderSwList(container: HTMLElement) { const corp = corpSelect ? corpSelect.value : ''; const filtered = fullList.filter(asset => { - const matchKeyword = !keyword || (asset.제품명 || '').toLowerCase().includes(keyword) || (asset.부서 || '').toLowerCase().includes(keyword); + const matchKeyword = !keyword || (asset[ASSET_SCHEMA.PRODUCT.key] || '').toLowerCase().includes(keyword) || (asset.부서 || '').toLowerCase().includes(keyword); const matchField = !field || asset.분야 === field; - const matchCorp = !corp || asset.법인 === corp; + const matchCorp = !corp || asset[ASSET_SCHEMA.CORP.key] === corp; return matchKeyword && matchField && matchCorp; }); tbody.innerHTML = ''; if (filtered.length === 0) { - tbody.innerHTML = `검색 결과가 없습니다.`; + tbody.innerHTML = `${UI_TEXT.MESSAGES.NO_DATA}`; return; } filtered.forEach((asset, idx) => { const assigned = state.masterData.swUsers.filter(u => u.sw_id === asset.id).length; - const qty = typeof asset.수량 === 'number' ? asset.수량 : parseInt(asset.수량||'0', 10); + const qty = typeof asset[ASSET_SCHEMA.QTY.key] === 'number' ? asset[ASSET_SCHEMA.QTY.key] : parseInt(asset[ASSET_SCHEMA.QTY.key]||'0', 10); const avail = qty - assigned; - let statusHtml = ''; + let statusBadge = ''; if (isSub) { let isExpired = false; - if (asset.구독일) { - const parts = asset.구독일.split('~'); + if (asset[ASSET_SCHEMA.EXPIRY.key]) { + const parts = asset[ASSET_SCHEMA.EXPIRY.key].split('~'); const endDateStr = parts[parts.length - 1].trim().replace(/\./g, '-'); const endDate = new Date(endDateStr); if (!isNaN(endDate.getTime())) { @@ -103,11 +105,9 @@ export function renderSwList(container: HTMLElement) { if (endDate < new Date()) isExpired = true; } } - if (isExpired) statusHtml = `만료`; - else statusHtml = `사용중`; + statusBadge = isExpired ? `만료` : `사용중`; } else { - if (asset.유지보수여부) statusHtml = `유효`; - else statusHtml = `없음`; + statusBadge = asset.유지보수여부 ? `유효` : `없음`; } const tr = document.createElement('tr'); @@ -115,35 +115,22 @@ export function renderSwList(container: HTMLElement) { tr.innerHTML = ` ${idx+1} - ${statusHtml} - ${asset.분야||''} - ${asset.법인} - ${asset.부서||''} - ${asset.제품명} - ${asset.구매일||''} - ${isSub ? `${asset.구독일||''}` : ''} - ${asset.금액||'0'} + ${statusBadge} + ${asset.분야||''} + ${asset[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()} ${qty} ${avail} - - - - `; - tr.addEventListener('click', (e) => { - if (!(e.target as HTMLElement).closest('button')) { - openSwModal(asset, 'view'); - } - }); - tr.querySelector('.btn-edit')?.addEventListener('click', (e) => { - e.stopPropagation(); - openSwModal(asset, 'edit'); - }); - tr.querySelector('.btn-users')?.addEventListener('click', (e) => { e.stopPropagation(); openSwUserModal(asset); }); + tr.addEventListener('click', () => openSwModal(asset, 'view')); tbody.appendChild(tr); }); - createIcons({ icons: { Edit2, Users, RefreshCcw } }); + createIcons({ icons: { RefreshCcw } }); }; document.getElementById('filter-keyword')?.addEventListener('input', updateTable); diff --git a/src/views/SW_Table.ts b/src/views/SW_Table.ts index adf666b..4802425 100644 --- a/src/views/SW_Table.ts +++ b/src/views/SW_Table.ts @@ -34,11 +34,16 @@ export function renderSWTable(mainContent: HTMLElement) { } else if (state.activeCategory === 'sw') { if (tab === '구독SW' || tab === '영구SW') { renderSwList(container); - } else if (tab === '클라우드') { - renderCloudList(container); } else { container.innerHTML = `
"${tab}" 탭에 대한 소프트웨어 리스트 뷰가 정의되지 않았습니다.
`; } + } else if (state.activeCategory === 'ops') { + // 운영 서비스 관련 탭 처리 + if (['도메인', '메일', '메신저', '청구비용'].includes(tab)) { + renderCloudList(container); // 일단 클라우드 리스트로 공통 처리 + } else { + container.innerHTML = `
"${tab}" 탭에 대한 운영 서비스 뷰가 정의되지 않았습니다.
`; + } } mainContent.appendChild(container);