From 05c565552a63cbce3bc09e16f6866fcf4f66d6d5 Mon Sep 17 00:00:00 2001 From: Taehoon Date: Mon, 8 Jun 2026 11:40:27 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9E=90=EC=82=B0=20=ED=98=84=ED=99=A9?= =?UTF-8?q?=20=EA=B3=A0=EB=8F=84=ED=99=94=20=EB=B0=8F=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=ED=91=9C=EC=A4=80=ED=99=94=20=EC=9E=91=EC=97=85=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UI 개선: 모든 아이콘/이모지 제거(미니멀리즘), 목록 행 하이라이트 추가, 요약 레이아웃 최적화 - 경고 시스템: 위치 부적절/형식 부적절 사유별 세분화 및 상단 통계 배지 적용 - 정보 강화: 우측 패널 '상세 보기' 버튼 복구 및 '자산 유형' 정보 추가 노출 - 표준화: 위치명(기술개발센터, 한맥빌딩) 및 자산번호 접두사(STO/NAS/DAS -> DSS/STM) 통합 - 데이터: realServerData.ts 및 SharedData.ts 내 유형/접두사 표준 체계 전면 반영 - 레이아웃: 헤더 역할 스위처 및 가이드 버튼 일렬 정렬 수정 --- src/components/Modal/SharedData.ts | 12 +- src/core/realServerData.ts | 46 +++---- src/styles/common.css | 1 + src/views/List/ListFactory.ts | 192 ++++++++++++++++++++--------- 4 files changed, 165 insertions(+), 86 deletions(-) diff --git a/src/components/Modal/SharedData.ts b/src/components/Modal/SharedData.ts index 6f374fe..f1d4e77 100644 --- a/src/components/Modal/SharedData.ts +++ b/src/components/Modal/SharedData.ts @@ -13,9 +13,9 @@ export const HW_STATUS_LIST = ['운영', '재고', '수리', '폐기', '기타'] // 구분(Category) -> 유형(Asset Type) 관계 정의 (통합 관리) export const CATEGORY_TYPE_MAP: Record = { - '서버': ['서버 렉', '가상서버(VM)', '워크스테이션', 'NAS', 'DAS', '서버PC', '스토리지 렉'], + '서버': ['서버 렉', '가상서버(VM)', '워크스테이션', '서버PC', '저장시스템_렉(NAS)', '저장시스템_렉(DAS)', '저장시스템_미니(NAS)', '저장시스템_미니(DAS)'], 'PC': ['개인PC', '노트북', '공용PC', '서버PC'], - '스토리지': ['SSD', 'HDD', '외장HDD'], + '저장매체': ['SSD', 'HDD', '외장HDD'], '네트워크': ['스위치', '허브', '방화벽', '라우터', '공유기', '허브'], 'PC부품': ['CPU', 'RAM', 'GPU', 'SSD', 'HDD', 'RAM', '모니터'], '공간정보장비': ['드론', '측량장비', '보조기기'], @@ -38,10 +38,12 @@ export const LOCATION_DATA: Record = { // 유형별 자산번호 접두사(Prefix) 매핑 export const TYPE_PREFIX_MAP: Record = { - '서버': 'SVR', '워크스테이션': 'SVR', '개인PC': 'PC', '공용PC': 'PC', '서버PC': 'PC', 'NAS': 'NAS', 'DAS': 'DAS', '스토리지': 'STO', - 'HDD': 'HDD', 'SSD': 'SSD', '노트북': 'NBK', '태블릿': 'TAB', + '서버': 'SVR', '워크스테이션': 'SVR', '개인PC': 'PC', '공용PC': 'PC', '서버PC': 'PC', + '저장시스템_렉(NAS)': 'DSS', '저장시스템_렉(DAS)': 'DSS', '저장시스템_미니(NAS)': 'DSS', '저장시스템_미니(DAS)': 'DSS', + '저장매체': 'STM', 'HDD': 'HDD', 'SSD': 'SSD', + '노트북': 'NBK', '태블릿': 'TAB', '드론': 'DRO', '측량장비': 'SUR', '보조기기': 'SUR', '허브': 'NET', - '구독SW': 'SW', '영구SW': 'SW', '내부' : 'INT' + '구독SW': 'SW', '영구SW': 'SW', '내부' : 'SW_INT', '외부':'SW_EXT' }; // 배치도 이미지 매핑 데이터 diff --git a/src/core/realServerData.ts b/src/core/realServerData.ts index c071f14..35cffab 100644 --- a/src/core/realServerData.ts +++ b/src/core/realServerData.ts @@ -484,7 +484,7 @@ export const realServerData = [ }, { "법인": "삼안", - "자산코드": "sa-das-001", + "자산코드": "DSS020", "storage유형": "서버", "용도": "", "상세": "Satis01, Satis02 광케이블 연결 (물리연결)", @@ -505,7 +505,7 @@ export const realServerData = [ }, { "법인": "삼안", - "자산코드": "sa-nas-001", + "자산코드": "DSS019", "storage유형": "서버", "용도": "인트라넷 백업 스토리지", "상세": "", @@ -526,7 +526,7 @@ export const realServerData = [ }, { "법인": "삼안", - "자산코드": "sa-nas-002", + "자산코드": "DSS018", "storage유형": "서버", "용도": "성과품 스토리지", "상세": "매니지먼트 접속 확인 불가 (콘솔 연결 후 페이지 오픈 필요)", @@ -547,7 +547,7 @@ export const realServerData = [ }, { "법인": "삼안", - "자산코드": "sa-nas-003", + "자산코드": "DSS017", "storage유형": "서버", "용도": "성과품 백업 스토리지", "상세": "", @@ -568,7 +568,7 @@ export const realServerData = [ }, { "법인": "한라", - "자산코드": "hl-das-001", + "자산코드": "DSS016", "storage유형": "서버", "용도": "", "상세": "파일서버 정보 없음(접속 불가)", @@ -589,7 +589,7 @@ export const realServerData = [ }, { "법인": "한라", - "자산코드": "hl-das-002", + "자산코드": "DSS015", "storage유형": "서버", "용도": "", "상세": "파일서버 정보 없음(접속 불가)", @@ -611,7 +611,7 @@ export const realServerData = [ { "법인": "", "자산코드": "", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "GSIM NAS", "상세": "팀 내부 자료 저장 , 정사영상 및 지도 데이터 저장 , Gitea 및 Git 내장 NAS", "위치": "마천사무실", @@ -631,7 +631,7 @@ export const realServerData = [ { "법인": "", "자산코드": "", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "그래픽스개발팀 데이터 백업 NAS", "상세": "그래픽스 개발팀 데이터 백업용 NAS", "위치": "마천사무실", @@ -1091,7 +1091,7 @@ export const realServerData = [ { "법인": "", "자산코드": "1", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "NAS 2", "상세": "한라 기업부설연구소 공용 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1107,7 +1107,7 @@ export const realServerData = [ { "법인": "", "자산코드": "2", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "NAS 1", "상세": "한라 공용 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1123,7 +1123,7 @@ export const realServerData = [ { "법인": "", "자산코드": "3", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "NAS 4", "상세": "한라 공용 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1139,7 +1139,7 @@ export const realServerData = [ { "법인": "", "자산코드": "4", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "NAS 5", "상세": "한라 환경플랜트사업부 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1155,7 +1155,7 @@ export const realServerData = [ { "법인": "", "자산코드": "5", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "NAS 6", "상세": "한라 공용 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1171,7 +1171,7 @@ export const realServerData = [ { "법인": "", "자산코드": "6", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "NAS7", "상세": "한라 원주바이오 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1187,7 +1187,7 @@ export const realServerData = [ { "법인": "", "자산코드": "7", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "총괄기획실 NAS", "상세": "총괄기획실 공용 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1203,7 +1203,7 @@ export const realServerData = [ { "법인": "", "자산코드": "8", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "한맥 NAS 1", "상세": "한맥 공용 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1219,7 +1219,7 @@ export const realServerData = [ { "법인": "", "자산코드": "9", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "한맥 NAS 2", "상세": "한맥 공용 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1235,7 +1235,7 @@ export const realServerData = [ { "법인": "", "자산코드": "10", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "한맥 NAS 3", "상세": "한맥 공용 NAS", "위치": "한맥빌딩(MDF 실)", @@ -1251,7 +1251,7 @@ export const realServerData = [ { "법인": "", "자산코드": "11", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "NAS 13", "상세": "환경플랜트사업", "위치": "한맥빌딩(MDF 실)", @@ -1331,7 +1331,7 @@ export const realServerData = [ { "법인": "", "자산코드": "16", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "디자인팀1 NAS", "상세": "", "위치": "한맥빌딩(MDF 실)", @@ -1347,7 +1347,7 @@ export const realServerData = [ { "법인": "", "자산코드": "17", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "디자인팀2 NAS", "상세": "", "위치": "한맥빌딩(MDF 실)", @@ -1507,7 +1507,7 @@ export const realServerData = [ { "법인": "", "자산코드": "27", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "기술개발센터 NAS", "상세": "", "위치": "한맥빌딩(MDF 실)", @@ -1523,7 +1523,7 @@ export const realServerData = [ { "법인": "", "자산코드": "28", - "storage유형": "NAS", + "storage유형": "저장시스템_렉(DAS)", "용도": "-", "상세": "", "위치": "한맥빌딩(MDF 실)", diff --git a/src/styles/common.css b/src/styles/common.css index 6f238ac..3bfbb77 100644 --- a/src/styles/common.css +++ b/src/styles/common.css @@ -112,6 +112,7 @@ body { .lnb-item:hover { color: var(--primary-color); background-color: var(--primary-light); } .lnb-item.active { color: var(--primary-color); background-color: var(--primary-light); font-weight: 700; } +.header-actions { display: flex; align-items: center; gap: 1rem; } .role-switcher { display: flex; align-items: center; gap: 0.75rem; padding: 0 0.75rem; border-right: 1px solid var(--border-color); height: 24px; } .role-label { font-size: 11px; font-weight: 700; color: var(--text-muted); } .role-label.active { color: var(--primary-color); } diff --git a/src/views/List/ListFactory.ts b/src/views/List/ListFactory.ts index 0c3ff4a..b7b1709 100644 --- a/src/views/List/ListFactory.ts +++ b/src/views/List/ListFactory.ts @@ -4,10 +4,6 @@ import { setupTableSorting, SortState } from '../../core/tableHandler'; import { renderFilterBar, applyCommonFilters } from '../../core/filterHandler'; import { state } from '../../core/state'; import { IMAGE_LOCATIONS } from '../../components/Modal/SharedData'; -import { - createIcons, RefreshCcw, Plus, Edit2, Trash2, Users, Cloud, - CreditCard, DollarSign, Paperclip, X -} from 'lucide'; export interface ColumnDef { header: string; @@ -93,6 +89,11 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { let internalCount = 0; let externalCount = 0; + const extTypeCounts: Record = {}; + const intTypeCounts: Record = {}; + let locWarningCount = 0; + let typeWarningCount = 0; + fullList.forEach(asset => { const loc = asset[ASSET_SCHEMA.LOCATION.key] || '미지정'; const serviceTypeKey = ASSET_SCHEMA.SERVICE_TYPE?.key || 'service_type'; @@ -109,14 +110,22 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { if (serviceType === '내부') { internalCount++; - if (loc === '기술개발센터') intSubCounts.tech++; - else if (loc === 'IDC') intSubCounts.idc++; - else if (loc === '한맥빌딩') intSubCounts.hm++; + if (loc.includes('기술개발')) intSubCounts.tech++; + else if (loc.includes('IDC')) intSubCounts.idc++; + else if (loc.includes('한맥')) intSubCounts.hm++; + if (type) intTypeCounts[type] = (intTypeCounts[type] || 0) + 1; } else { externalCount++; - if (loc === '기술개발센터') extSubCounts.tech++; - else if (loc === 'IDC') extSubCounts.idc++; - else if (loc === '한맥빌딩') extSubCounts.hm++; + if (loc.includes('기술개발')) extSubCounts.tech++; + else if (loc.includes('IDC')) extSubCounts.idc++; + else if (loc.includes('한맥')) extSubCounts.hm++; + if (type) extTypeCounts[type] = (extTypeCounts[type] || 0) + 1; + + // [경고 로직 세분화] 외부 운영 기준 (공백/대소문자 무시) + if (serviceType === '외부') { + if (loc !== 'IDC') locWarningCount++; + if (type.toLowerCase().replace(/\s/g, '').includes('서버pc')) typeWarningCount++; + } } }); @@ -126,7 +135,6 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { const chartLabels = isPcView ? pcLabels : locLabels; const chartData = isPcView ? pcData : locLabels.map(l => locationCounts[l]); - const chartColors = ['#1E5149', '#4255bd', '#92400E', '#B91C1C', '#6D28D9', '#BE185D', '#0369A1', '#15803D', '#4B5563']; contentWrapper.innerHTML = `
@@ -136,28 +144,40 @@ export function createListView(container: HTMLElement, config: ListViewConfig) {
총 보유 자산
${fullList.length}
-
- 외부: ${externalCount} - 내부: ${internalCount} +
+ 외부: ${externalCount} + 내부: ${internalCount}
${isPcView ? `
PC 유형별 현황
-
- 공용: ${pcTypeCounts.public} - 서버: ${pcTypeCounts.server} - 개인: ${pcTypeCounts.personal} +
+ 공용: ${pcTypeCounts.public} + 서버: ${pcTypeCounts.server} + 개인: ${pcTypeCounts.personal}
` : ` -
- 외부 (운영) 상세 +
+ 외부 (운영) 상세 +
+ ${locWarningCount > 0 ? `위치부적절: ${locWarningCount}` : ''} + ${typeWarningCount > 0 ? `형식부적절: ${typeWarningCount}` : ''} +
-
- 기술개발센터: ${extSubCounts.tech} - IDC: ${extSubCounts.idc} - 한맥빌딩: ${extSubCounts.hm} +
+
+ 기술개발센터: ${extSubCounts.tech} + IDC: ${extSubCounts.idc} + 한맥빌딩: ${extSubCounts.hm} +
+
+ ${Object.entries(extTypeCounts).sort((a, b) => b[1] - a[1]).map(([type, count]) => { + const isTypeWarning = type.toLowerCase().replace(/\s/g, '').includes('서버pc'); + return `${type}: ${count}`; + }).join('')} +
`}
@@ -165,12 +185,17 @@ export function createListView(container: HTMLElement, config: ListViewConfig) {
${isPcView ? '' : `
- 내부 (테스트) 상세 + 내부 (테스트) 상세
-
- 기술개발센터: ${intSubCounts.tech} - IDC: ${intSubCounts.idc} - 한맥빌딩: ${intSubCounts.hm} +
+
+ 기술개발센터: ${intSubCounts.tech} + IDC: ${intSubCounts.idc} + 한맥빌딩: ${intSubCounts.hm} +
+
+ ${Object.entries(intTypeCounts).sort((a, b) => b[1] - a[1]).map(([type, count]) => `${type}: ${count}`).join('')} +
`}
@@ -178,7 +203,7 @@ export function createListView(container: HTMLElement, config: ListViewConfig) {
-
+

자산 현황 목록

@@ -195,7 +220,7 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { - + @@ -208,22 +233,28 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { -
+
-
🖼️

목록에서 자산을 선택하면
상세 정보와 배치도가 표시됩니다.

- - + + + @@ -379,12 +441,26 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { }).join(''); tbody.querySelectorAll('.mini-row').forEach(row => { row.addEventListener('click', () => { + tbody.querySelectorAll('.mini-row').forEach(r => { + const rIsWarning = (r as HTMLElement).style.borderLeftColor === 'rgb(225, 29, 72)'; // E11D48 + (r as HTMLElement).style.backgroundColor = rIsWarning ? '#FFF1F2' : 'transparent'; + }); + (row as HTMLElement).style.backgroundColor = '#EBF2F1'; // 선택 하이라이트 const id = (row as HTMLElement).getAttribute('data-id'); const asset = fullList.find(a => a.id === id); if (asset) updateDetailPanel(asset); }); - row.addEventListener('mouseenter', () => { (row as HTMLElement).style.backgroundColor = '#F8FAFA'; }); - row.addEventListener('mouseleave', () => { (row as HTMLElement).style.backgroundColor = 'transparent'; }); + row.addEventListener('mouseenter', () => { + if ((row as HTMLElement).style.backgroundColor !== 'rgb(235, 242, 241)') { + (row as HTMLElement).style.backgroundColor = '#F8FAFA'; + } + }); + row.addEventListener('mouseleave', () => { + const isWarning = (row as HTMLElement).style.borderLeftColor === 'rgb(225, 29, 72)'; + if ((row as HTMLElement).style.backgroundColor !== 'rgb(235, 242, 241)') { + (row as HTMLElement).style.backgroundColor = isWarning ? '#FFF1F2' : 'transparent'; + } + }); }); } }; @@ -454,7 +530,7 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { updateTable(); }); - createIcons({ icons: { RefreshCcw, Plus, Edit2, Trash2, Users, Cloud, CreditCard, DollarSign, Paperclip } }); + // createIcons call removed as icons are no longer needed in dashboard }; // --- 뷰 전환 로직 ---
분류분류 용도/자산명 관리자(정) 관리자(부)
${serviceType}${purpose || '-'}
+
+ ${serviceType} + ${isWarning ? `${warningReason}` : ''} +
+
${purpose || '-'} ${managerMain} ${managerSub} ${asset[ASSET_SCHEMA.LOC_DETAIL.key] || '-'}