Compare commits
150 Commits
PC_Table
...
db_setting
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f165faf13 | ||
|
|
237ac9ee25 | ||
| f41f2378d7 | |||
| 41406f56e8 | |||
| af578a63bc | |||
| e8bc42e5de | |||
| 587e92a7da | |||
| c6515c1b5d | |||
| e128634e05 | |||
| c0ef52deac | |||
| aab1f91d3d | |||
| f656f0a439 | |||
| e77c4854cb | |||
| 1d32a0350b | |||
| 309c400ee2 | |||
| 3db05f2939 | |||
| 2cb4b87c0a | |||
| 6ed2faee2d | |||
| 89d3ac2e89 | |||
| b37981506e | |||
| abc531a41e | |||
| 8451101325 | |||
| 3e69e74bc9 | |||
| 73ef13f3a5 | |||
| 155570e8de | |||
| 723c4723f6 | |||
| a44283281f | |||
| fa87f383e2 | |||
| 6118141f6e | |||
| 119c799d1d | |||
| 05e23883b8 | |||
| 8c406fd0b8 | |||
| e678f9d653 | |||
| 132e37d0d3 | |||
| d6e75f8b2c | |||
| c35f57acab | |||
| 97cecb8b50 | |||
| b9d28736e2 | |||
| a4b620099c | |||
| b169176d57 | |||
| 56abdddbc7 | |||
| fd9e88d7c6 | |||
| 407b9ba531 | |||
| 55c43aa250 | |||
| 9186eb50ca | |||
| 8a3727ea61 | |||
| 0c1977f707 | |||
| 19e6be27de | |||
| accbbdc2fa | |||
| d3c4fa5e66 | |||
| 8c1cb6cf93 | |||
| 4810df212a | |||
| f5a84a77ef | |||
| 565802f55b | |||
| 10479aad7e | |||
| 95fbd3f606 | |||
| 207acbdecb | |||
| 164568843b | |||
| 29c7d5f3d8 | |||
| ce1ed40561 | |||
| 525dbd77d4 | |||
| 35c5b1e0fa | |||
| b87ca2854b | |||
| 2f88a0fae7 | |||
| 9a2c35e652 | |||
| 25ebaf4685 | |||
| 2b9c965c91 | |||
| 4b408b0640 | |||
| 3ab587d342 | |||
| 3b9b2ea598 | |||
| 05c565552a | |||
| 2ec9261c03 | |||
| 06f3baaa58 | |||
| eead43837d | |||
| 46422e8544 | |||
| a30f99f0ad | |||
| 34d99dc4b6 | |||
| bb859dddfc | |||
| 9e8ab11f99 | |||
| 19d4222470 | |||
| db5c7a96a6 | |||
| 7d3d5ef281 | |||
| 9cd5d59bf8 | |||
| 590ddd0e85 | |||
| bf7fb0ffe6 | |||
| 2c67037fc4 | |||
| b2713a142d | |||
| 82bbe85e23 | |||
| d34ebb8500 | |||
| 2af79cdad3 | |||
| 68cb5f9767 | |||
| 8f0508a7d0 | |||
| 171bcc772b | |||
| ab0d25b827 | |||
| d7af75976e | |||
| dde3aefaac | |||
| 1fbd297988 | |||
| 4b5e25fd3f | |||
| 367f72673d | |||
| 9fcecd4bf5 | |||
| d125de1902 | |||
| d8a0c47fb3 | |||
| 4b88ac01a4 | |||
| 5feaa5f170 | |||
| 9365af4522 | |||
| 55e9cd4cd9 | |||
| bb1cc36d01 | |||
| e5b4eb8295 | |||
| b996b18dbc | |||
| e147b1a191 | |||
| 925a55bcc6 | |||
| 809f3fcf3b | |||
| 9d9c482b76 | |||
| 11e2f3b4ca | |||
| e1cdcfd93a | |||
| fdc29b23c1 | |||
| af37df7f2d | |||
| d52c2c4200 | |||
| 4b765aba2e | |||
| 7247737ce0 | |||
| e4d958b5f2 | |||
| ba7ce796d1 | |||
| 5ff991693a | |||
| a576d54a2d | |||
| fca9f5caf8 | |||
| 34baea9143 | |||
| d983ad469f | |||
| 153e422180 | |||
| 213bbe4734 | |||
| d8824ca0e1 | |||
| 1ace678c09 | |||
| 5248b494e9 | |||
| 5372cda59f | |||
| 415727a866 | |||
| c5d7f4cf67 | |||
| 90d94739a2 | |||
| 6904925146 | |||
| 6053c746a3 | |||
| 97478dd9bc | |||
| b3f7920176 | |||
| c5c6acea6a | |||
| 54bfb9d482 | |||
| 7158689fd0 | |||
| fde7ef8439 | |||
| a805d9ce06 | |||
| 7c4ccf6bba | |||
| 3c28c664da | |||
| d94be9a494 | |||
| 157330b06d | |||
| e4914ee66d |
6
.env
Normal file
@@ -0,0 +1,6 @@
|
||||
DB_HOST=172.16.8.151
|
||||
DB_PORT=3306
|
||||
DB_USER=itam_admin
|
||||
DB_PASS=itam1234
|
||||
DB_NAME=itam
|
||||
PORT=3000
|
||||
2
.gitignore
vendored
@@ -1,5 +1,5 @@
|
||||
node_modules/
|
||||
.gemini/
|
||||
.gemini
|
||||
.env
|
||||
dist/
|
||||
*.log
|
||||
|
||||
36
README.md
@@ -9,6 +9,17 @@
|
||||
- 기존 동작 방식과 성능을 기준(Baseline)으로 삼고, 수정 후에도 **기존의 모든 기능이 무결하게 유지되는지 반드시 테스트하여 입증**한다.
|
||||
- 검증 결과를 바탕으로 "무엇을, 왜, 어떻게" 바꿀지 상세 보고 후, 사용자로부터 **'진행시켜'** 승인을 얻은 뒤에만 집행한다.
|
||||
4. **선보고 후승인**: 모든 기능 수정 및 코드 변경 전에는 예상 방안을 먼저 보고하고 승인 절차를 거친다.
|
||||
5. **DB 삭제 및 초기화 절대 엄금 (Strict DB Deletion Policy)**:
|
||||
- 어떠한 경우에도 `DELETE`, `DROP`, `TRUNCATE` 등 데이터를 삭제하거나 테이블을 초기화하는 작업은 사전에 사용자에게 상세 사유를 보고하고 **명시적 승인**을 얻은 후에만 시행한다.
|
||||
- 기존 데이터의 가치를 최우선으로 하며, 작업 전 백업 여부를 반드시 확인한다.
|
||||
6. **RED–GREEN–Refactor 개발 원칙**:
|
||||
- 모든 기능 개발과 버그 수정은 **RED → GREEN → Refactor** 순서로 진행한다.
|
||||
- **RED**: 요구사항을 명확히 표현하는 테스트를 먼저 작성하고, 해당 테스트가 기능 미구현 또는 결함으로 인해 실패하는지 확인한다.
|
||||
- **GREEN**: 실패한 테스트를 통과시키는 데 필요한 최소한의 코드만 구현하며, 불필요한 기능 추가나 구조 변경을 하지 않는다.
|
||||
- **Refactor**: 관련 테스트와 기존 테스트가 모두 통과하는 상태에서만 중복 제거, 명칭 개선, 책임 분리 등 코드 구조를 개선하며 동작은 변경하지 않는다.
|
||||
- 각 단계가 끝날 때마다 관련 테스트와 기존 기능의 회귀 여부를 검증한다.
|
||||
- 테스트 작성이 현실적으로 불가능한 경우에는 그 사유와 대체 검증 방법을 먼저 보고하고 승인을 받은 후 진행한다.
|
||||
- 본 원칙을 적용할 때에도 기존의 **선보고 후승인** 및 **외과 수술식 수정** 규칙을 준수한다.
|
||||
|
||||
---
|
||||
|
||||
@@ -28,29 +39,8 @@
|
||||
|
||||
### 🎨 ITAM 시스템 디자인 가이드 (Design Guide)
|
||||
|
||||
1. **디자인 철학 (Design Philosophy)**
|
||||
* **Minimalist & Border-based**: 불필요한 박스(Card) 사용을 최소화하고, 정보의 구분은 간결한 라인(Border/Divider)을 활용하여 시각적 피로도를 낮춥니다.
|
||||
* **Professional Achromatic**: 무채색(Black, White, Grey)을 기본으로 하여 정돈된 업무 환경을 제공합니다.
|
||||
* **Green Accent**: 블루 대신 짙은 그린(`#1E5149`)을 포인트 컬러로 사용하여 차분한 전문성을 강조합니다.
|
||||
디자인 일관성 및 시각적 원칙에 관한 상세 내용은 아래 문서를 참조하십시오.
|
||||
|
||||
2. **타이포그래피 (Typography)**
|
||||
* **Font Family**: `Pretendard` (전역 적용)
|
||||
* **Letter Spacing**: `-0.02em` (약 -2%) 적용. 자간을 좁게 설정하여 밀도 있고 세련된 가독성을 확보합니다.
|
||||
* **Weights**: 400(Regular), 500(Medium), 600(SemiBold), 700(Bold).
|
||||
👉 **[디자인 가이드 바로가기 (design_rule.md)](./design_rule.md)**
|
||||
|
||||
3. **컬러 팔레트 (Color Palette)**
|
||||
* **Point Color**: `#1E5149` (Deep Green) - 강조, 활성화 상태, 주요 액션 버튼.
|
||||
* **Text**: Main(`#111827` - Near Black), Muted(`#6B7280` - Grey).
|
||||
* **Border/Divider**: `#E5E7EB` (Light Grey) - 정보 구분을 위한 얇은 실선.
|
||||
* **Background**: `#FFFFFF` (White) / `#F9FAFB` (Off White).
|
||||
|
||||
4. **레이아웃 및 컴포넌트 규칙 (Layout Rules)**
|
||||
* **Box-less Design**: 꼭 필요한 정보 묶음(데이터 그룹화 등)이 아니면 박스 형태의 테두리나 배경 사용을 지양합니다.
|
||||
* **Line-based Division**: 섹션 간의 구분은 1px 두께의 얇은 실선(Border)을 통해 명확히 합니다.
|
||||
* **Table**: 배경색이나 화려한 효과 없이 행(Row) 간의 얇은 구분선만 사용하여 데이터 본연에 집중하게 합니다.
|
||||
* **Input/Button**: 입력 필드와 버튼은 최소한의 보더와 포인트 컬러만 사용하여 정갈하게 표현합니다.
|
||||
* **Modal (모달 공통 규칙)**:
|
||||
* **Header**: 짙은 그린(`#1E5149`) 배경에 화이트 텍스트를 사용하며, 우측 상단에 명확한 'X' 닫기 버튼을 배치합니다.
|
||||
* **Interaction**: 사용자의 편의를 위해 `ESC` 키를 누르거나 모달 바깥 영역(Overlay)을 클릭하면 모달이 닫히도록 구현합니다.
|
||||
* **Layout**: `detail.png` 기준의 2열 그리드 시스템을 권장하며, 하단 우측에 액션 버튼(닫기, 저장 등)을 배치합니다.
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# 🛠️ 개발 및 관리 규칙 (Strict Development Rules)
|
||||
|
||||
1. **언어 설정**: 영어로 생각하되, 모든 답변은 **한국어**로 작성한다.
|
||||
2. **임의 수정 절대 금지 (Zero-Arbitrary Change)**:
|
||||
- 사용자가 명시적으로 지시한 부분 외에는 **단 한 줄의 코드도, 그 어떤 파일도 임의로 수정, 정리, 리팩토링하지 않는다.**
|
||||
- 지시받지 않은 다른 파트의 코드는 절대 건드리지 않으며, 영향 범위가 요청 범위를 벗어나지 않도록 '외과 수술식(Surgical) 수정'을 원칙으로 한다.
|
||||
3. **개선 작업 절차 (Test-First Approach)**:
|
||||
- 사용자가 개선(Refactoring, Optimization 등)을 지시한 경우, **수정 전 현재 시스템이 정상적으로 잘 작동하는지 먼저 전수 확인**한다.
|
||||
- 기존 동작 방식과 성능을 기준(Baseline)으로 삼고, 수정 후에도 **기존의 모든 기능이 무결하게 유지되는지 반드시 테스트하여 입증**한다.
|
||||
- 검증 결과를 바탕으로 "무엇을, 왜, 어떻게" 바꿀지 상세 보고 후, 사용자로부터 **'진행시켜'** 승인을 얻은 뒤에만 집행한다.
|
||||
4. **선보고 후승인**: 모든 기능 수정 및 코드 변경 전에는 예상 방안을 먼저 보고하고 승인 절차를 거친다.
|
||||
|
||||
---
|
||||
|
||||
### 🚀 서버 구동 및 외부 접속 규칙 (Server Run & External Access)
|
||||
|
||||
1. **포트 고정**: 개발 서버는 반드시 **8080** 포트를 사용한다. (`vite.config.ts` 설정 준수)
|
||||
2. **외부 접속 허용 (Host)**: 사무실 내 타 직원이 접속할 수 있도록 `--host` 모드로 구동한다.
|
||||
3. **구동 명령어**:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
* 해당 명령어 실행 시 `0.0.0.0` 또는 `Network: http://[내-IP]:8080/` 경로로 타인 접속이 가능하다.
|
||||
4. **IP 확인 방법**:
|
||||
* Windows: `ipconfig` 명령어로 'IPv4 주소' 확인 후 공유.
|
||||
|
||||
---
|
||||
|
||||
### 🎨 ITAM 시스템 디자인 가이드 (Design Guide)
|
||||
|
||||
1. **디자인 철학 (Design Philosophy)**
|
||||
* **Minimalist & Border-based**: 불필요한 박스(Card) 사용을 최소화하고, 정보의 구분은 간결한 라인(Border/Divider)을 활용하여 시각적 피로도를 낮춥니다.
|
||||
* **Professional Achromatic**: 무채색(Black, White, Grey)을 기본으로 하여 정돈된 업무 환경을 제공합니다.
|
||||
* **Green Accent**: 블루 대신 짙은 그린(`#1E5149`)을 포인트 컬러로 사용하여 차분한 전문성을 강조합니다.
|
||||
|
||||
2. **타이포그래피 (Typography)**
|
||||
* **Font Family**: `Pretendard` (전역 적용)
|
||||
* **Letter Spacing**: `-0.02em` (약 -2%) 적용. 자간을 좁게 설정하여 밀도 있고 세련된 가독성을 확보합니다.
|
||||
* **Weights**: 400(Regular), 500(Medium), 600(SemiBold), 700(Bold).
|
||||
* **Date Format (날짜 표기 규칙)**: 시스템 내 모든 날짜는 `YYYY.MM.DD` 형식을 기본으로 사용합니다. (예: 2026.04.10)
|
||||
|
||||
3. **컬러 팔레트 (Color Palette)**
|
||||
* **Point Color**: `#1E5149` (Deep Green) - 강조, 활성화 상태, 주요 액션 버튼.
|
||||
* **Text**: Main(`#111827` - Near Black), Muted(`#6B7280` - Grey).
|
||||
* **Border/Divider**: `#E5E7EB` (Light Grey) - 정보 구분을 위한 얇은 실선.
|
||||
* **Background**: `#FFFFFF` (White) / `#F9FAFB` (Off White).
|
||||
|
||||
4. **레이아웃 및 컴포넌트 규칙 (Layout Rules)**
|
||||
* **Box-less Design**: 꼭 필요한 정보 묶음(데이터 그룹화 등)이 아니면 박스 형태의 테두리나 배경 사용을 지양합니다.
|
||||
* **Line-based Division**: 섹션 간의 구분은 1px 두께의 얇은 실선(Border)을 통해 명확히 합니다.
|
||||
* **Table**: 배경색이나 화려한 효과 없이 행(Row) 간의 얇은 구분선만 사용하여 데이터 본연에 집중하게 합니다.
|
||||
* **Input/Button**: 입력 필드와 버튼은 최소한의 보더와 포인트 컬러만 사용하여 정갈하게 표현합니다.
|
||||
* **Modal (모달 공통 규칙)**:
|
||||
* **Header**: 짙은 그린(`#1E5149`) 배경에 화이트 텍스트를 사용하며, 우측 상단에 명확한 'X' 닫기 버튼을 배치합니다.
|
||||
* **Interaction**: 사용자의 편의를 위해 `ESC` 키를 누르거나 모달 바깥 영역(Overlay)을 클릭하면 모달이 닫히도록 구현합니다.
|
||||
* **Layout**: `detail.png` 기준의 2열 그리드 시스템을 권장하며, 하단 우측에 액션 버튼(닫기, 저장 등)을 배치합니다.
|
||||
|
||||
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 195 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 53 KiB |
@@ -1,13 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" as="style" crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.css" />
|
||||
<title>ITAM - IT Asset Management</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,32 +0,0 @@
|
||||
# 📑 ITAM 시스템 통합 구축 기획서 (plan.md)
|
||||
|
||||
## 1. 프로젝트 목적 (Objective)
|
||||
본 시스템은 **'전산자산번호 부여방안'** 표준 가이드에 따라 사내 모든 전산 자산을 통합 관리하는 것을 목적으로 한다. 분산된 자산 정보를 일원화된 번호 체계로 시스템화하여 직관적인 식별과 정밀한 이력 추적이 가능한 플랫폼을 지향한다.
|
||||
|
||||
## 2. 자산번호 체계 적용 (Standardization)
|
||||
검토안에 따라 모든 자산은 다음과 같은 규칙으로 고유 번호를 부여받으며, 시스템의 핵심 Key로 활용된다.
|
||||
|
||||
* **번호 생성 규칙**: `[구매법인]-[설치위치]-[자산종류]-[일련번호(구매연월+3자리)]`
|
||||
* *예시: 삼안에서 2025년 4월에 구매한 IDC 서버 → `SM-IDC-SVR-202504001`*
|
||||
* **코드 정의**:
|
||||
* **구매법인**: BR(바론), SM(삼안), HM(한맥), JH(장헌), HL(한라), PTC(PTC) 등
|
||||
* **설치위치**: TDC(센터 서버실), HBD(한맥빌딩), IDC(IDC), UBD(유니온 빌딩), NBD(뉴코아 빌딩) 등
|
||||
* **자산종류**: SVR(서버), PC(PC), STO(스토리지), NAS(NAS), DAS(DAS), HDD(하드) 등
|
||||
|
||||
## 3. 기획 의도 및 시스템 가치 (Core Intent)
|
||||
1. **식별 용이성 확보**: 번호만으로도 법인, 위치, 종류, 도입 시기를 즉시 파악할 수 있는 시스템 UI를 제공한다.
|
||||
2. **전사 통합 관리 로드맵**:
|
||||
* **Phase 1**: IDC 서버 및 스토리지 데이터 마이그레이션 (현재 완료 단계)
|
||||
* **Phase 2**: 센터 서버실(TDC) 및 빌딩별 네트워크 장비 확장
|
||||
* **Phase 3**: 전사 개인 PC(PC) 및 하드웨어 부품(HDD 등) 통합
|
||||
* **Phase 4**: 소프트웨어 라이선스와 하드웨어 자산의 매핑 관리
|
||||
3. **데이터 무결성 유지**: 자산 위치 변경 시 기존 번호를 폐기하고 신규 번호를 부여하는 이력 관리 원칙을 시스템상에서 강제 및 기록한다.
|
||||
|
||||
## 4. 시스템 주요 기능 (Key Features)
|
||||
* **자산 자동 번호 부여**: 입력 폼에서 법인/위치/종류 선택 시 가이드에 따른 자산번호 자동 생성 기능.
|
||||
* **상세 이력 카드**: 자산번호를 클릭하면 상세 사양, 취득일, 사용자, 현재 상태 및 과거 이동 이력을 모달로 표시.
|
||||
* **통합 필터링**: 법인별, 위치별, 종류별로 자산을 즉시 분류하여 조회할 수 있는 고성능 테이블 제공.
|
||||
|
||||
## 5. 기술 및 디자인 원칙 (Engineering Standards)
|
||||
* **Design**: `README.md` 가이드를 준수하며, 자산번호가 가장 강조되는 레이아웃을 유지한다.
|
||||
* **Data Structure**: 향후 DB 전환 시 자산번호의 각 코드(SM, IDC 등)를 정규화하여 관리 효율을 극대화한다.
|
||||
@@ -1,295 +0,0 @@
|
||||
:root {
|
||||
--primary-color: #1E5149;
|
||||
--primary-hover: #163d37;
|
||||
--bg-default: #FFFFFF;
|
||||
--bg-muted: #F9FAFB;
|
||||
--info-color: #4B5563; /* 무채색 계열로 변경 */
|
||||
--text-main: #111827;
|
||||
--text-muted: #6B7280;
|
||||
--border-color: #E5E7EB;
|
||||
}
|
||||
|
||||
.app-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
background-color: var(--bg-default);
|
||||
color: var(--text-main);
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
height: 50px;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 40px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.top-bar-brand {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
margin-right: 48px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.top-bar-menu {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-weight: 500;
|
||||
font-size: 0.875rem;
|
||||
height: 100%;
|
||||
border-bottom: 3px solid transparent;
|
||||
}
|
||||
|
||||
.menu-item:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.menu-item.active {
|
||||
color: white;
|
||||
border-bottom: 3px solid white;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - 50px);
|
||||
overflow: hidden; /* 전체 페이지 스크롤 방지 */
|
||||
padding: 0; /* 패딩은 내부 요소에서 관리 */
|
||||
}
|
||||
|
||||
.content-header {
|
||||
padding: 32px 40px 16px 40px;
|
||||
margin-bottom: 0;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: var(--bg-default);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: 0 40px 40px 40px;
|
||||
}
|
||||
|
||||
.content-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
/* Common Table Styles */
|
||||
.data-table {
|
||||
width: 100%;
|
||||
border-collapse: separate; /* sticky border 유지를 위해 separate 사용 */
|
||||
border-spacing: 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.data-table th, .data-table td {
|
||||
padding: 14px 12px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.data-table th {
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
background-color: #F8FAFC; /* 헤더 전용 배경색 */
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
}
|
||||
|
||||
.data-table tr:hover {
|
||||
background-color: var(--bg-muted);
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--primary-hover);
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
background-color: var(--bg-muted);
|
||||
}
|
||||
|
||||
/* Dashboard Stats - Border based */
|
||||
.dashboard-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 0;
|
||||
margin-bottom: 48px;
|
||||
border-top: 1px solid var(--border-color);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.stat-card:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* Modal Styles */
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: var(--bg-default);
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
padding: 16px 24px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-close-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
opacity: 0.8;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.modal-close-btn:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 24px;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.detail-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px 24px;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.detail-item.full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.detail-item label {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-muted);
|
||||
background-color: var(--bg-default);
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 16px 24px;
|
||||
border-top: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
background-color: var(--bg-muted);
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import './App.css'
|
||||
import AssetManagementView from './components/AssetManagementView'
|
||||
import HardwareManagementView from './components/HardwareManagementView'
|
||||
|
||||
function App() {
|
||||
const [activeMenu, setActiveMenu] = useState('assets')
|
||||
|
||||
const renderContent = () => {
|
||||
switch (activeMenu) {
|
||||
case 'assets':
|
||||
return <AssetManagementView />
|
||||
case 'hardware':
|
||||
return <HardwareManagementView />
|
||||
default:
|
||||
return <AssetManagementView />
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app-container">
|
||||
<header className="top-bar">
|
||||
<div className="top-bar-brand">
|
||||
ITAM System
|
||||
</div>
|
||||
<nav className="top-bar-menu">
|
||||
<div
|
||||
className={`menu-item ${activeMenu === 'assets' ? 'active' : ''}`}
|
||||
onClick={() => setActiveMenu('assets')}
|
||||
>
|
||||
전산자산관리대장
|
||||
</div>
|
||||
<div
|
||||
className={`menu-item ${activeMenu === 'hardware' ? 'active' : ''}`}
|
||||
onClick={() => setActiveMenu('hardware')}
|
||||
>
|
||||
H/W 사양 정보
|
||||
</div>
|
||||
<div className="menu-item">S/W 설치 현황</div>
|
||||
<div className="menu-item">라이선스 관리</div>
|
||||
<div className="menu-item">실물 자산 관리</div>
|
||||
</nav>
|
||||
</header>
|
||||
<main className="main-content">
|
||||
{renderContent()}
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
@@ -1,168 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import { idcServers, idcStorages, IdcServer } from '../data/idcData'
|
||||
import ServerDetailModal from './ServerDetailModal'
|
||||
|
||||
const AssetManagementView = () => {
|
||||
const [viewMode, setViewMode] = useState<'server' | 'storage'>('server')
|
||||
const [selectedServer, setSelectedServer] = useState<IdcServer | null>(null)
|
||||
|
||||
return (
|
||||
<div className="asset-management" style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||
<div className="content-header">
|
||||
<div className="content-title">전산자산관리대장 (IDC)</div>
|
||||
<div style={{ display: 'flex', gap: '12px' }}>
|
||||
<button
|
||||
className={`btn ${viewMode === 'server' ? 'btn-primary' : 'btn-outline'}`}
|
||||
onClick={() => setViewMode('server')}
|
||||
>
|
||||
서버 목록
|
||||
</button>
|
||||
<button
|
||||
className={`btn ${viewMode === 'storage' ? 'btn-primary' : 'btn-outline'}`}
|
||||
onClick={() => setViewMode('storage')}
|
||||
>
|
||||
스토리지 목록
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-container">
|
||||
<div style={{ padding: '24px 0 16px 0' }}>
|
||||
<h3 style={{ fontSize: '1.125rem', fontWeight: 600, color: 'var(--primary-color)', margin: 0 }}>
|
||||
{viewMode === 'server' ? 'IDC 서버 상세 정보' : 'IDC 스토리지 상세 정보'}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{viewMode === 'server' ? (
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>회사</th>
|
||||
<th>서버번호</th>
|
||||
<th>구분</th>
|
||||
<th>설치위치</th>
|
||||
<th>관리자</th>
|
||||
<th>IP 주소</th>
|
||||
<th>접속 정보</th>
|
||||
<th>H/W 사양</th>
|
||||
<th>OS</th>
|
||||
<th>구매일</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{idcServers.map((server) => (
|
||||
<tr key={server.serverNo} onClick={() => setSelectedServer(server)} style={{ cursor: 'pointer' }}>
|
||||
<td style={{ fontWeight: 600 }}>{server.company}</td>
|
||||
<td style={{ color: 'var(--primary-color)', fontWeight: 500 }}>{server.serverNo}</td>
|
||||
<td>
|
||||
<div>{server.category}</div>
|
||||
{server.remarks && <div style={{ fontSize: '0.75rem', color: 'var(--text-muted)' }}>{server.remarks}</div>}
|
||||
</td>
|
||||
<td>{server.location}</td>
|
||||
<td>
|
||||
<div style={{ fontWeight: 500 }}>{server.managerPrimary ? `정: ${server.managerPrimary}` : '정: -'}</div>
|
||||
<div style={{ fontSize: '0.75rem', color: 'var(--text-muted)' }}>{server.managerSecondary ? `부: ${server.managerSecondary}` : '부: -'}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{server.ip1}</div>
|
||||
{server.ip2 && <div style={{ fontSize: '0.75rem', color: 'var(--text-muted)' }}>{server.ip2}</div>}
|
||||
</td>
|
||||
<td>
|
||||
{server.remoteAccess.map((access, idx) => (
|
||||
<div key={idx} style={{
|
||||
marginBottom: idx < server.remoteAccess.length - 1 ? '8px' : 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '2px'
|
||||
}}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
|
||||
<span style={{ fontSize: '0.7rem', backgroundColor: '#f3f4f6', padding: '1px 4px', borderRadius: '2px', color: 'var(--text-muted)', fontWeight: 600 }}>{access.tool}</span>
|
||||
<span style={{ fontSize: '0.8125rem', fontWeight: 500 }}>{access.id}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: '0.75rem', color: 'var(--text-muted)', paddingLeft: '4px', borderLeft: '1px solid var(--border-color)', marginLeft: '4px' }}>
|
||||
PW: <span style={{ color: 'var(--text-main)' }}>{access.pw}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</td>
|
||||
<td style={{ fontSize: '0.8125rem' }}>
|
||||
<div style={{ fontWeight: 500 }}>{server.model}</div>
|
||||
<div style={{ color: 'var(--text-muted)' }}>{server.cpu} / {server.ram}</div>
|
||||
<div style={{ color: 'var(--text-muted)' }}>{server.storage.join(' + ')}</div>
|
||||
</td>
|
||||
<td style={{ fontSize: '0.8125rem' }}>{server.os}</td>
|
||||
<td style={{ fontSize: '0.8125rem' }}>{server.purchaseDate}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
) : (
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>회사</th>
|
||||
<th>서버번호</th>
|
||||
<th>구분</th>
|
||||
<th>설치위치</th>
|
||||
<th>관리자</th>
|
||||
<th>IP 주소</th>
|
||||
<th>접속 정보</th>
|
||||
<th>모델명</th>
|
||||
<th>용량</th>
|
||||
<th>구매일</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{idcStorages.map((storage) => (
|
||||
<tr key={storage.serverNo}>
|
||||
<td style={{ fontWeight: 600 }}>{storage.company}</td>
|
||||
<td style={{ color: 'var(--primary-color)', fontWeight: 500 }}>{storage.serverNo}</td>
|
||||
<td>
|
||||
<div>{storage.category}</div>
|
||||
{storage.remarks && <div style={{ fontSize: '0.75rem', color: 'var(--text-muted)' }}>{storage.remarks}</div>}
|
||||
</td>
|
||||
<td>{storage.location}</td>
|
||||
<td>
|
||||
<span style={{ fontWeight: 500 }}>정: {storage.managerPrimary}</span>
|
||||
<span style={{ fontSize: '0.75rem', color: 'var(--text-muted)', marginLeft: '8px' }}>부: {storage.managerSecondary}</span>
|
||||
</td>
|
||||
<td>{storage.ip}</td>
|
||||
<td>
|
||||
{storage.remoteAccess.map((access, idx) => (
|
||||
<div key={idx} style={{
|
||||
marginBottom: idx < storage.remoteAccess.length - 1 ? '8px' : 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '2px'
|
||||
}}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
|
||||
<span style={{ fontSize: '0.7rem', backgroundColor: '#f3f4f6', padding: '1px 4px', borderRadius: '2px', color: 'var(--text-muted)', fontWeight: 600 }}>{access.tool}</span>
|
||||
<span style={{ fontSize: '0.8125rem', fontWeight: 500 }}>{access.id}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: '0.75rem', color: 'var(--text-muted)', paddingLeft: '4px', borderLeft: '1px solid var(--border-color)', marginLeft: '4px' }}>
|
||||
PW: <span style={{ color: 'var(--text-main)' }}>{access.pw}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</td>
|
||||
<td>{storage.model}</td>
|
||||
<td style={{ fontWeight: 600 }}>{storage.capacity}</td>
|
||||
<td>{storage.purchaseDate}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{selectedServer && (
|
||||
<ServerDetailModal
|
||||
server={selectedServer}
|
||||
onClose={() => setSelectedServer(null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AssetManagementView
|
||||
@@ -1,51 +0,0 @@
|
||||
import { mockCategories } from '../data/mockData'
|
||||
|
||||
const DashboardView = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="content-header">
|
||||
<div className="content-title">대시보드</div>
|
||||
</div>
|
||||
|
||||
<div className="dashboard-stats">
|
||||
<div className="stat-card">
|
||||
<div className="stat-label">전체 자산</div>
|
||||
<div className="stat-value">8개</div>
|
||||
</div>
|
||||
{mockCategories.map(cat => (
|
||||
<div key={cat.id} className="stat-card">
|
||||
<div className="stat-label">{cat.name}</div>
|
||||
<div className="stat-value">{cat.count}개</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="card">
|
||||
<h3>최근 변경 내역</h3>
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>날짜</th>
|
||||
<th>내용</th>
|
||||
<th>사용자</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>2023-04-11</td>
|
||||
<td>PC 신규 등록</td>
|
||||
<td>이관형</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2023-04-10</td>
|
||||
<td>모니터 부서 할당 변경</td>
|
||||
<td>관리자</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DashboardView
|
||||
@@ -1,87 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import { mockHardwareSpecs, HardwareSpec } from '../data/mockData'
|
||||
|
||||
const SpecModal = ({ spec, onClose }: { spec: HardwareSpec, onClose: () => void }) => {
|
||||
return (
|
||||
<div style={{
|
||||
position: 'fixed', top: 0, left: 0, width: '100%', height: '100%',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)', display: 'flex', justifyContent: 'center', alignItems: 'center',
|
||||
zIndex: 1000
|
||||
}}>
|
||||
<div className="card" style={{ width: '600px', maxWidth: '90%' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '20px' }}>
|
||||
<h2>상세 사양 정보</h2>
|
||||
<button className="btn" onClick={onClose}>×</button>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', gap: '10px' }}>
|
||||
<strong>PC명:</strong> <span>{spec.pcName}</span>
|
||||
<strong>사용자:</strong> <span>{spec.userName}</span>
|
||||
<strong>부서:</strong> <span>{spec.department}</span>
|
||||
<strong>OS:</strong> <span>{spec.os}</span>
|
||||
<strong>CPU:</strong> <span>{spec.cpu}</span>
|
||||
<strong>Memory:</strong> <span>{spec.memory}</span>
|
||||
<strong>Disk:</strong> <span>{spec.disk}</span>
|
||||
<strong>MAC:</strong> <span>{spec.macAddress}</span>
|
||||
<strong>IP:</strong> <span>{spec.ipAddress}</span>
|
||||
<strong>Graphic:</strong> <span>{spec.graphicCard}</span>
|
||||
</div>
|
||||
<div style={{ marginTop: '20px', textAlign: 'right' }}>
|
||||
<button className="btn btn-primary" onClick={onClose}>닫기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const HardwareManagementView = () => {
|
||||
const [selectedSpec, setSelectedSpec] = useState<HardwareSpec | null>(null)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="content-header">
|
||||
<div className="content-title">H/W 사양 정보</div>
|
||||
</div>
|
||||
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PC명</th>
|
||||
<th>부서</th>
|
||||
<th>사용자</th>
|
||||
<th>OS</th>
|
||||
<th>CPU</th>
|
||||
<th>IP주소</th>
|
||||
<th>상세</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{mockHardwareSpecs.map(spec => (
|
||||
<tr key={spec.id}>
|
||||
<td>{spec.pcName}</td>
|
||||
<td>{spec.department}</td>
|
||||
<td>{spec.userName}</td>
|
||||
<td>{spec.os.split(' ')[2]}</td>
|
||||
<td title={spec.cpu}>{spec.cpu.split('@')[0]}</td>
|
||||
<td>{spec.ipAddress}</td>
|
||||
<td>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
style={{ padding: '4px 8px', fontSize: '0.8rem' }}
|
||||
onClick={() => setSelectedSpec(spec)}
|
||||
>
|
||||
보기
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{selectedSpec && (
|
||||
<SpecModal spec={selectedSpec} onClose={() => setSelectedSpec(null)} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HardwareManagementView
|
||||
@@ -1,144 +0,0 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { IdcServer } from '../data/idcData';
|
||||
|
||||
interface ServerDetailModalProps {
|
||||
server: IdcServer;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const ServerDetailModal: React.FC<ServerDetailModalProps> = ({ server, onClose }) => {
|
||||
// ESC 키로 모달 닫기
|
||||
useEffect(() => {
|
||||
const handleEsc = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', handleEsc);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleEsc);
|
||||
};
|
||||
}, [onClose]);
|
||||
|
||||
return (
|
||||
<div className="modal-overlay" onClick={onClose}>
|
||||
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="modal-header">
|
||||
<h2 style={{ margin: 0, fontSize: '1.125rem', fontWeight: 600 }}>{server.category} ({server.serverNo})</h2>
|
||||
<button className="modal-close-btn" onClick={onClose} aria-label="Close modal">×</button>
|
||||
</div>
|
||||
|
||||
<div className="modal-body">
|
||||
<div className="detail-grid">
|
||||
{/* Row 1 */}
|
||||
<div className="detail-item">
|
||||
<label>회사 구분</label>
|
||||
<div className="detail-value">{server.company}</div>
|
||||
</div>
|
||||
<div className="detail-item">
|
||||
<label>서버 번호</label>
|
||||
<div className="detail-value" style={{ color: 'var(--primary-color)', fontWeight: 600 }}>{server.serverNo}</div>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="detail-item">
|
||||
<label>자산명(용도)</label>
|
||||
<div className="detail-value">{server.category}</div>
|
||||
</div>
|
||||
<div className="detail-item">
|
||||
<label>설치 위치</label>
|
||||
<div className="detail-value">{server.location}</div>
|
||||
</div>
|
||||
|
||||
{/* Row 3: 관리자 추가 */}
|
||||
<div className="detail-item full-width">
|
||||
<label>관리 담당자</label>
|
||||
<div className="detail-value">
|
||||
<span style={{ fontWeight: 600, color: 'var(--text-main)' }}>정: {server.managerPrimary}</span>
|
||||
<span style={{ marginLeft: '16px', color: 'var(--text-muted)' }}>부: {server.managerSecondary}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 4 */}
|
||||
<div className="detail-item">
|
||||
<label>IP 주소 1</label>
|
||||
<div className="detail-value">{server.ip1 || '-'}</div>
|
||||
</div>
|
||||
<div className="detail-item">
|
||||
<label>IP 주소 2</label>
|
||||
<div className="detail-value">{server.ip2 || '-'}</div>
|
||||
</div>
|
||||
|
||||
{/* Row 5 */}
|
||||
<div className="detail-item full-width">
|
||||
<label>원격 접속 정보</label>
|
||||
<div className="detail-value">
|
||||
{server.remoteAccess.length > 0 ? (
|
||||
<div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>
|
||||
{server.remoteAccess.map((access, idx) => (
|
||||
<div key={idx} style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '4px 8px', backgroundColor: 'var(--bg-muted)', borderRadius: '4px', border: '1px solid var(--border-color)' }}>
|
||||
<span style={{ fontSize: '0.75rem', fontWeight: 600, color: 'var(--text-muted)' }}>{access.tool}</span>
|
||||
<span style={{ fontWeight: 500 }}>{access.id}</span>
|
||||
<span style={{ color: 'var(--border-color)' }}>|</span>
|
||||
<span>PW: <span style={{ color: 'var(--text-main)' }}>{access.pw}</span></span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : '-'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 6 */}
|
||||
<div className="detail-item">
|
||||
<label>제조사 및 모델명</label>
|
||||
<div className="detail-value">{server.model || '-'}</div>
|
||||
</div>
|
||||
<div className="detail-item">
|
||||
<label>OS</label>
|
||||
<div className="detail-value">{server.os || '-'}</div>
|
||||
</div>
|
||||
|
||||
{/* Row 7 */}
|
||||
<div className="detail-item">
|
||||
<label>CPU</label>
|
||||
<div className="detail-value">{server.cpu || '-'}</div>
|
||||
</div>
|
||||
<div className="detail-item">
|
||||
<label>RAM</label>
|
||||
<div className="detail-value">{server.ram || '-'}</div>
|
||||
</div>
|
||||
|
||||
{/* Row 8 */}
|
||||
<div className="detail-item full-width">
|
||||
<label>Storage (디스크 구성)</label>
|
||||
<div className="detail-value">{server.storage.length > 0 ? server.storage.join(' + ') : '-'}</div>
|
||||
</div>
|
||||
|
||||
{/* Row 9 */}
|
||||
<div className="detail-item">
|
||||
<label>구매일자</label>
|
||||
<div className="detail-value">{server.purchaseDate || '-'}</div>
|
||||
</div>
|
||||
<div className="detail-item">
|
||||
<label>모니터링 여부</label>
|
||||
<div className="detail-value">{server.monitoring || '-'}</div>
|
||||
</div>
|
||||
|
||||
{/* Row 10 */}
|
||||
<div className="detail-item full-width">
|
||||
<label>비고 및 특이사항</label>
|
||||
<div className="detail-value" style={{ minHeight: '40px' }}>{server.remarks || '-'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-outline" onClick={onClose} style={{ marginRight: '8px' }}>닫기</button>
|
||||
<button className="btn btn-primary" onClick={onClose}>수정(저장)</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerDetailModal;
|
||||
@@ -1,608 +0,0 @@
|
||||
export interface RemoteAccess {
|
||||
tool: string;
|
||||
ip?: string;
|
||||
id: string;
|
||||
pw: string;
|
||||
}
|
||||
|
||||
export interface IdcServer {
|
||||
company: string;
|
||||
serverNo: string;
|
||||
category: string;
|
||||
remarks: string;
|
||||
location: string;
|
||||
managerPrimary: string;
|
||||
managerSecondary: string;
|
||||
ip1: string;
|
||||
ip2: string;
|
||||
remoteAccess: RemoteAccess[];
|
||||
monitoring: string;
|
||||
serverIdMatch: string;
|
||||
model: string;
|
||||
os: string;
|
||||
cpu: string;
|
||||
ram: string;
|
||||
storage: string[];
|
||||
purchaseDate: string;
|
||||
}
|
||||
|
||||
export interface IdcStorage {
|
||||
company: string;
|
||||
serverNo: string;
|
||||
category: string;
|
||||
remarks: string;
|
||||
location: string;
|
||||
managerPrimary: string;
|
||||
managerSecondary: string;
|
||||
ip: string;
|
||||
managementIp?: string;
|
||||
remoteAccess: RemoteAccess[];
|
||||
model: string;
|
||||
capacity: string;
|
||||
purchaseDate: string;
|
||||
}
|
||||
|
||||
export const idcServers: IdcServer[] = [
|
||||
{
|
||||
company: "한맥",
|
||||
serverNo: "hm-idc-001",
|
||||
category: "한맥 인트라넷",
|
||||
remarks: "",
|
||||
location: "서관 204번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "211.206.127.70",
|
||||
ip2: "192.168.10.5",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "samanerp1!" },
|
||||
{ tool: "Remote Util", id: "211.206.127.70", pw: "1234아이티!" }
|
||||
],
|
||||
monitoring: "win exp, raid X",
|
||||
serverIdMatch: "srv07d330084",
|
||||
model: "HPE ProLiant DL360 Gen10",
|
||||
os: "Windows Server 2016",
|
||||
cpu: "intel xeon silver4110 CPU @2.10GHz",
|
||||
ram: "32GB",
|
||||
storage: ["280GB", "2.7TB"],
|
||||
purchaseDate: "2020.12.10"
|
||||
},
|
||||
{
|
||||
company: "한맥",
|
||||
serverNo: "hm-idc-002",
|
||||
category: "한맥 인트라넷 예비",
|
||||
remarks: "단가, 입사자지원 서버 (스마트 건설 용도 구매)",
|
||||
location: "서관 205번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "211.206.127.78",
|
||||
ip2: "192.168.10.13",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "Hanmac2141!" }
|
||||
],
|
||||
monitoring: "win exp, raid X",
|
||||
serverIdMatch: "srcff5294c84",
|
||||
model: "HPE ProLiant DL360 Gen10",
|
||||
os: "Windows Server 2019",
|
||||
cpu: "intel xeon silver4214R CPU @2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["280GB", "2.7TB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-001",
|
||||
category: "삼안 인트라넷",
|
||||
remarks: "",
|
||||
location: "서관 204번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "118.220.172.237",
|
||||
ip2: "erp.samaneng.com",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "samanerp1!" },
|
||||
{ tool: "Remote Util", id: "118.220.172.237", pw: "1234아이티!" }
|
||||
],
|
||||
monitoring: "O",
|
||||
serverIdMatch: "newSmintranet",
|
||||
model: "HPE ProLiant DL360 Gen10",
|
||||
os: "Windows Server 2016",
|
||||
cpu: "intel xeon silver4214R CPU @2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["280GB", "3.27TB"],
|
||||
purchaseDate: "2019.12.20"
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-002",
|
||||
category: "삼안 인트라넷 예비",
|
||||
remarks: "",
|
||||
location: "서관 204번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "118.220.172.249",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "samanerp1!" },
|
||||
{ tool: "Remote Util", id: "678-605-383-130", pw: "1234아이티!" }
|
||||
],
|
||||
monitoring: "설치 X",
|
||||
serverIdMatch: "INTRANET",
|
||||
model: "HPE ProLiant DL360 GEN9",
|
||||
os: "Windows Server 2008 R2",
|
||||
cpu: "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["279GB", "2.72TB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-003",
|
||||
category: "SATIS 01",
|
||||
remarks: "구 SATIS 서버, 세금계산서 발행(회계)",
|
||||
location: "서관 204번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "118.220.172.228",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "satissg11707808" }
|
||||
],
|
||||
monitoring: "설치 X",
|
||||
serverIdMatch: "satis01",
|
||||
model: "HPE ProLiant DL380p GEN8",
|
||||
os: "Windows Server 2008 R2",
|
||||
cpu: "Intel(R) Xeon(R) CPU E5-2643 0 @ 3.30GHz",
|
||||
ram: "20GB",
|
||||
storage: ["100GB", "458GB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-004",
|
||||
category: "SATIS 02",
|
||||
remarks: "SATIS 리뉴얼 버전 (ERP 서버)",
|
||||
location: "서관 204번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "118.220.172.229",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "satissg11707808" }
|
||||
],
|
||||
monitoring: "설치 X",
|
||||
serverIdMatch: "satis02",
|
||||
model: "HPE ProLiant DL380p GEN8",
|
||||
os: "Windows Server 2008 R2",
|
||||
cpu: "Intel(R) Xeon(R) CPU E5-2643 0 @ 3.30GHz",
|
||||
ram: "20GB",
|
||||
storage: ["100GB", "458GB", "18.1TB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-005",
|
||||
category: "웹 서버",
|
||||
remarks: "남양주 테스트 서버 (도메인 관리 기능 제거 2026.03.11)",
|
||||
location: "서관 204번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "samanweb.cafe24.com",
|
||||
ip2: "118.220.172.195",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "saman+2013+web" }
|
||||
],
|
||||
monitoring: "win exp, 포트 안열림",
|
||||
serverIdMatch: "www",
|
||||
model: "HPE ProLiant DL380p GEN8",
|
||||
os: "Windwos Server 2012",
|
||||
cpu: "Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz",
|
||||
ram: "16GB",
|
||||
storage: ["100GB", "230GB", "230GB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-006",
|
||||
category: "PQ DB 서버",
|
||||
remarks: "",
|
||||
location: "서관 204번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "118.220.172.231",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "7013ddj10235!" }
|
||||
],
|
||||
monitoring: "O",
|
||||
serverIdMatch: "src5dd67f2ed",
|
||||
model: "HPE ProLiant DL360 Gen10",
|
||||
os: "Windows Server 2019",
|
||||
cpu: "intel xeon silver4210R CPU @2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["278GB", "2.18TB"],
|
||||
purchaseDate: "2024.12.16"
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-007",
|
||||
category: "Oracle DB 서버",
|
||||
remarks: "",
|
||||
location: "서관 202번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "118.220.172.225",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "7013ddj10235!" }
|
||||
],
|
||||
monitoring: "win exp, raid X",
|
||||
serverIdMatch: "SAMAN-DB",
|
||||
model: "HPE ProLiant DL380 GEN9",
|
||||
os: "Windows Server 2012",
|
||||
cpu: "Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz",
|
||||
ram: "64GB",
|
||||
storage: ["558GB", "1.09TB", "1.09TB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-008",
|
||||
category: "안전관리",
|
||||
remarks: "삼안 개발서버2 - AI, SSL, 장헌TBM, 노드",
|
||||
location: "서관 202번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "1.234.37.171",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "samanerp1!" }
|
||||
],
|
||||
monitoring: "연결 X",
|
||||
serverIdMatch: "",
|
||||
model: "HPE ProLiant DL380 GEN10",
|
||||
os: "Windwos Server 2022",
|
||||
cpu: "Intel Xeon(R) Silver 4210R CPU @ 2.40GHz",
|
||||
ram: "128GB",
|
||||
storage: ["278GB", "3.27TB"],
|
||||
purchaseDate: "2025.04.10"
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-idc-009",
|
||||
category: "가족사 공통메뉴",
|
||||
remarks: "삼안 개발서버1 - QNA, 급여명세서",
|
||||
location: "서관 202번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "118.220.172.233",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "samanerp1!" }
|
||||
],
|
||||
monitoring: "O",
|
||||
serverIdMatch: "srcc9ac928ee",
|
||||
model: "HPE ProLiant DL380 GEN10",
|
||||
os: "Windwos Server 2022",
|
||||
cpu: "Intel Xeon(R) Silver 4210R CPU @ 2.40GHz",
|
||||
ram: "128GB",
|
||||
storage: ["278GB", "3.27TB"],
|
||||
purchaseDate: "2025.04.10"
|
||||
},
|
||||
{
|
||||
company: "한라",
|
||||
serverNo: "hl-idc-001",
|
||||
category: "한라 인트라넷",
|
||||
remarks: "인트라넷,안전, 운영, MISO 서버로 운영 중(win 2008)",
|
||||
location: "동관 54번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "1.234.37.143",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "Remote Util", id: "1.234.37.143", pw: "1234dkdlxl!" }
|
||||
],
|
||||
monitoring: "설치 X",
|
||||
serverIdMatch: "",
|
||||
model: "HPE ProLiant DL360 GEN9",
|
||||
os: "Windows Server 2008 R2",
|
||||
cpu: "Intel(R) Xeon(R) CPU E5-2603 v4 @ 1.70GHz",
|
||||
ram: "8GB",
|
||||
storage: ["299GB", "631GB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "한라",
|
||||
serverNo: "hl-idc-002",
|
||||
category: "안전전산화 서버 (디자인팀 웹)",
|
||||
remarks: "인트라넷 서버 다운 시 백업용 대기",
|
||||
location: "동관 54번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "1.234.37.144",
|
||||
ip2: "192.168.20.49",
|
||||
remoteAccess: [
|
||||
{ tool: "Remote Util", id: "1.234.37.144", pw: "1234dkdlxl!" }
|
||||
],
|
||||
monitoring: "O",
|
||||
serverIdMatch: "",
|
||||
model: "HPE ProLiant DL360 GEN9",
|
||||
os: "Windows Server 2012",
|
||||
cpu: "Intel(R) Xeon(R) CPU E5-2603 v4 @ 1.70GHz",
|
||||
ram: "8GB",
|
||||
storage: ["299GB", "631GB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "한라",
|
||||
serverNo: "hl-idc-003",
|
||||
category: "개발서버2",
|
||||
remarks: "PTC 연구비로 구매한 예비서버2",
|
||||
location: "동관 53번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "192.168.20.171",
|
||||
ip2: "1.234.37.171",
|
||||
remoteAccess: [
|
||||
{ tool: "Remote Util", id: "1.234.37.171", pw: "1234dkdlxl!" }
|
||||
],
|
||||
monitoring: "O",
|
||||
serverIdMatch: "",
|
||||
model: "HPE ProLiant DL380 Gen10",
|
||||
os: "Windows Server 2019 Standard",
|
||||
cpu: "Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["280GB", "1TB"],
|
||||
purchaseDate: "2022.09.21"
|
||||
},
|
||||
{
|
||||
company: "장헌",
|
||||
serverNo: "jh-idc-001",
|
||||
category: "장헌인트라넷",
|
||||
remarks: "BEPs",
|
||||
location: "서관 205번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "211.206.127.71",
|
||||
ip2: "192.168.10.6",
|
||||
remoteAccess: [
|
||||
{ tool: "Remote Util", id: "211.206.127.71", pw: "1234dkdlxl!" },
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "Hanmac2141!%" }
|
||||
],
|
||||
monitoring: "잠금 걸려있음",
|
||||
serverIdMatch: "src775d3e5df",
|
||||
model: "HPE ProLiant DL380 GEN10",
|
||||
os: "Windows Server 2019",
|
||||
cpu: "Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["280GB", "1TB"],
|
||||
purchaseDate: "2022.09.21"
|
||||
},
|
||||
{
|
||||
company: "장헌",
|
||||
serverNo: "jh-idc-002",
|
||||
category: "장헌 인트라넷 예비",
|
||||
remarks: "",
|
||||
location: "동관 53번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "1.234.37.170",
|
||||
ip2: "192.168.20.170",
|
||||
remoteAccess: [
|
||||
{ tool: "Remote Util", id: "1.234.37.170", pw: "1234dkdlxl!" },
|
||||
{ tool: "원격데스크탑", id: "Administrator", pw: "Hanmac2141!" }
|
||||
],
|
||||
monitoring: "원격 X, O",
|
||||
serverIdMatch: "",
|
||||
model: "HPE ProLiant DL360 Gen10",
|
||||
os: "Windows Server 2019",
|
||||
cpu: "Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["280GB", "1TB"],
|
||||
purchaseDate: "2022.04.01"
|
||||
},
|
||||
{
|
||||
company: "장헌",
|
||||
serverNo: "jh-idc-003",
|
||||
category: "인트라넷(구)",
|
||||
remarks: "현재는 GIT 백업 으로 사용",
|
||||
location: "서관 205번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "211.206.127.110",
|
||||
ip2: "192.168.10.40",
|
||||
remoteAccess: [
|
||||
{ tool: "Remote Util", id: "211.206.127.110", pw: "1234dkdlxl!" },
|
||||
{ tool: "원격데스크탑", id: "User", pw: "Hanmac2141!" }
|
||||
],
|
||||
monitoring: "",
|
||||
serverIdMatch: "",
|
||||
model: "",
|
||||
os: "Windows Server 2019",
|
||||
cpu: "Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz",
|
||||
ram: "",
|
||||
storage: [],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "(주)장헌",
|
||||
serverNo: "jh-idc-004",
|
||||
category: "(주) 장헌 인트라넷",
|
||||
remarks: "2025.12.23 IDC 이전 설치",
|
||||
location: "서관 205번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "211.206.127.76",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "User", pw: "Hanmac2141!%" }
|
||||
],
|
||||
monitoring: "win exp, raid X",
|
||||
serverIdMatch: "DESKTOP-5IL75B7",
|
||||
model: "",
|
||||
os: "Windows 10",
|
||||
cpu: "12th Gen Intel(R) Core(TM) i7-12700F",
|
||||
ram: "32GB",
|
||||
storage: ["465GB", "1.81TB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "PTC",
|
||||
serverNo: "ptc-idc-001",
|
||||
category: "PTC인트라넷",
|
||||
remarks: "2024.05.22 인트라넷서버로 교체",
|
||||
location: "서관 205번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "211.206.127.72",
|
||||
ip2: "192.168.10.7",
|
||||
remoteAccess: [
|
||||
{ tool: "Remote Util", id: "211.206.127.72", pw: "1234dkdlxl!" }
|
||||
],
|
||||
monitoring: "설치 X",
|
||||
serverIdMatch: "",
|
||||
model: "SYSTEM X3650 M2",
|
||||
os: "Windows Server 2008 R2",
|
||||
cpu: "Intel(R) Xeon(R) CPU E5520 @ 2.27GHz",
|
||||
ram: "16GB",
|
||||
storage: ["556GB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "PTC",
|
||||
serverNo: "ptc-idc-002",
|
||||
category: "예비서버",
|
||||
remarks: "PTC 인트라넷 예비서버",
|
||||
location: "서관 204번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "192.168.10.8",
|
||||
ip2: "",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "1234dkdlxl!" }
|
||||
],
|
||||
monitoring: "O",
|
||||
serverIdMatch: "",
|
||||
model: "HPE ProLiant DL360 GEN10",
|
||||
os: "Windows Server 2019",
|
||||
cpu: "Intel Xeon(R) Silver 4210R CPU @ 2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["278GB", "1.09TB"],
|
||||
purchaseDate: "2022.04.01"
|
||||
},
|
||||
{
|
||||
company: "PTC",
|
||||
serverNo: "ptc-idc-003",
|
||||
category: "DB 백업 서버",
|
||||
remarks: "2024.05.22 변경 (데스크탑)",
|
||||
location: "서관 205번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "211.206.127.74",
|
||||
ip2: "192.168.10.9",
|
||||
remoteAccess: [
|
||||
{ tool: "Remote Util", id: "211.206.127.74", pw: "1234dkdlxl!" }
|
||||
],
|
||||
monitoring: "설치 X",
|
||||
serverIdMatch: "",
|
||||
model: "",
|
||||
os: "Window 7",
|
||||
cpu: "Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz",
|
||||
ram: "4GB",
|
||||
storage: ["593GB", "1.23TB"],
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "바론",
|
||||
serverNo: "br-idc-001",
|
||||
category: "인트라넷",
|
||||
remarks: "",
|
||||
location: "서관 205번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "211.206.127.75",
|
||||
ip2: "192.168.10.10",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "Hanmac2141!%" }
|
||||
],
|
||||
monitoring: "O",
|
||||
serverIdMatch: "srcf0136042d",
|
||||
model: "HPE ProLiant DL360 GEN10",
|
||||
os: "Windows Server 2022",
|
||||
cpu: "Intel Xeon(R) Silver 4210R CPU @ 2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["280GB", "2.18TB"],
|
||||
purchaseDate: "2025.04.14"
|
||||
},
|
||||
{
|
||||
company: "현타",
|
||||
serverNo: "ht-idc-001",
|
||||
category: "인트라넷",
|
||||
remarks: "",
|
||||
location: "동관 53번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip1: "1.234.37.172",
|
||||
ip2: "192.168.20.172",
|
||||
remoteAccess: [
|
||||
{ tool: "원격데스크탑", id: "administrator", pw: "Hanmac2141!" }
|
||||
],
|
||||
monitoring: "O",
|
||||
serverIdMatch: "src901e49933",
|
||||
model: "HPE ProLiant DL380 GEN10",
|
||||
os: "Windows Server 2019",
|
||||
cpu: "Intel Xeon Silver 4210R CPU @ 2.40GHz",
|
||||
ram: "32GB",
|
||||
storage: ["280GB", "1TB"],
|
||||
purchaseDate: "2022.09.21"
|
||||
}
|
||||
];
|
||||
|
||||
export const idcStorages: IdcStorage[] = [
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-nas-001",
|
||||
category: "인트라넷 백업 스토리지",
|
||||
remarks: "",
|
||||
location: "서관 203번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip: "118.220.172.246",
|
||||
remoteAccess: [{ tool: "원격", id: "administrator", pw: "sg11707808" }],
|
||||
model: "Promiss R Series",
|
||||
capacity: "36TB",
|
||||
purchaseDate: ""
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-nas-002",
|
||||
category: "성과품 스토리지",
|
||||
remarks: "매니지먼트 접속 확인 불가",
|
||||
location: "서관 205번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip: "118.220.172.248",
|
||||
managementIp: "118.220.172.247",
|
||||
remoteAccess: [{ tool: "원격", id: "administrator", pw: "sg11707808" }],
|
||||
model: "ENC_3U_16BAY_D",
|
||||
capacity: "23TB",
|
||||
purchaseDate: "2019.06.03"
|
||||
},
|
||||
{
|
||||
company: "삼안",
|
||||
serverNo: "sa-nas-003",
|
||||
category: "성과품 백업 스토리지",
|
||||
remarks: "",
|
||||
location: "서관 202번",
|
||||
managerPrimary: "김철수",
|
||||
managerSecondary: "홍길동",
|
||||
ip: "118.220.172.241",
|
||||
managementIp: "118.220.172.240",
|
||||
remoteAccess: [
|
||||
{ tool: "원격", id: "administrator", pw: "saman1!" },
|
||||
{ tool: "원격", id: "admin0", pw: "Root1234" }
|
||||
],
|
||||
model: "Promiss R Series",
|
||||
capacity: "48TB",
|
||||
purchaseDate: "2025.03.13"
|
||||
}
|
||||
];
|
||||
@@ -1,84 +0,0 @@
|
||||
export interface Category {
|
||||
id: string;
|
||||
name: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface Asset {
|
||||
id: string;
|
||||
categoryName: string;
|
||||
name: string;
|
||||
quantity: number;
|
||||
internalCode: string;
|
||||
serialNumber: string;
|
||||
department: string;
|
||||
user: string;
|
||||
acquisitionDate: string;
|
||||
status: string;
|
||||
location: string;
|
||||
}
|
||||
|
||||
export interface HardwareSpec {
|
||||
id: string;
|
||||
pcName: string;
|
||||
department: string;
|
||||
userName: string;
|
||||
os: string;
|
||||
cpu: string;
|
||||
memory: string;
|
||||
disk: string;
|
||||
macAddress: string;
|
||||
ipAddress: string;
|
||||
graphicCard: string;
|
||||
}
|
||||
|
||||
export const mockCategories: Category[] = [
|
||||
{ id: '1', name: 'PC', count: 1 },
|
||||
{ id: '2', name: '모니터', count: 5 },
|
||||
{ id: '3', name: '노트북', count: 2 },
|
||||
];
|
||||
|
||||
export const mockAssets: Asset[] = [
|
||||
{
|
||||
id: '1',
|
||||
categoryName: 'PC',
|
||||
name: 'PC',
|
||||
quantity: 1,
|
||||
internalCode: 'PC20230411001',
|
||||
serialNumber: 'SN-001-A1',
|
||||
department: '한맥기술',
|
||||
user: '이관형',
|
||||
acquisitionDate: '2023-04-11',
|
||||
status: '정상',
|
||||
location: '본사 3층',
|
||||
},
|
||||
];
|
||||
|
||||
export const mockHardwareSpecs: HardwareSpec[] = [
|
||||
{
|
||||
id: '1',
|
||||
pcName: 'DESKTOP-G1DVL26',
|
||||
department: '한맥기술',
|
||||
userName: '이준권',
|
||||
os: 'Microsoft Windows 10 Pro 10.0.19044',
|
||||
cpu: 'Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz',
|
||||
memory: 'Samsung 4 GB / Samsung 4 GB',
|
||||
disk: 'ST2000DM001-1CH164 1.82 TB / Samsung SSD 850 EVO 120GB',
|
||||
macAddress: '0862664B98A3',
|
||||
ipAddress: '172.16.9.68',
|
||||
graphicCard: 'NVIDIA GeForce GTX 750',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
pcName: 'DESKTOP-BNBPOUP',
|
||||
department: '한맥기술',
|
||||
userName: '주완기 연구원',
|
||||
os: 'Microsoft Windows 10 Pro 10.0.19045',
|
||||
cpu: 'Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz',
|
||||
memory: 'Samsung 8 GB / Samsung 8 GB',
|
||||
disk: 'ST1000DM003-1CH162 931.51 GB / Samsung SSD 840 EVO 120GB',
|
||||
macAddress: 'E03F4948ECC6',
|
||||
ipAddress: '172.16.9.23',
|
||||
graphicCard: 'Intel(R) HD Graphics 4600',
|
||||
},
|
||||
];
|
||||
@@ -1,26 +0,0 @@
|
||||
:root {
|
||||
font-family: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.02em;
|
||||
|
||||
color-scheme: light;
|
||||
color: #111827;
|
||||
background-color: #F9FAFB;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
#root {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.tsx'
|
||||
import './index.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
@@ -1,49 +0,0 @@
|
||||
IDC,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
서버목록,,,,,,,,,,,,,,,,,,,,,,,,,,한맥,LMS 서버,mdf,
|
||||
회사,서버번호,구분,비고,설치위치,담당자,,IP 주소,,원격접속,,,모니터링 여부,"서버 이름 ID
|
||||
일치 여부, 전 서버 이름",제조사 및 모델명,OS,CPU,RAM,Storage1,Storage2,Storage3,계산서,,,,,삼안,XR플래그십 스토리지,,20250414
|
||||
,,,,,정,부,IP,IP2,접속도구,아이디,비빌번호,,,,,,,,,,,,,,,장헌,"스토리지, 서버",mdf 추정,
|
||||
한맥,hm-idc-001,한맥 인트라넷,,서관 204번,,,211.206.127.70,192.168.10.5,원격데스크탑,administrator,samanerp1!,"win exp, raid X",srv07d330084,HPE ProLiant DL360 Gen10,Windows Server 2016,intel xeon silver4110 CPU @2.10GHz 2.10GHZ,32GB,280GB,2.7TB,,20201210 추정,한맥,,,,한라,백업서버,mdf,
|
||||
,,,,,,,,,Remote Util,211.206.127.70,1234아이티!,,,,,,,,,,,,,,,,,,
|
||||
,hm-idc-002,한맥 인트라넷 예비,"단가, 입사자지원 서버 (4/1 장헌산업 이름으로 스마트 건설 용도 구매)",서관 205번,,,211.206.127.78,192.168.10.13,원격데스크탑,administrator,Hanmac2141!,"win exp, raid X",srcff5294c84,HPE ProLiant DL360 Gen10,Windows Server 2019,intel xeon silver4214R CPU @2.40GHz 2.39GHZ,32GB,280GB,2.7TB,,,,,,,,,,
|
||||
삼안,sa-idc-001,삼안 인트라넷,,서관 204번,,,118.220.172.237,erp.samaneng.com,원격데스크탑,administrator,samanerp1!,O,newSmintranet,HPE ProLiant DL360 Gen10,Windows Server 2016,intel xeon silver4214R CPU @2.40GHz 2.39GHZ,32GB,280GB,3.27TB,,20191220 추정,삼안,,,,,,,
|
||||
,,,,,,,,,Remote Util,118.220.172.237,1234아이티!,,,,,,,,,,,,,,,,,,
|
||||
,sa-idc-002,삼안 인트라넷 예비,,서관 204번,,,118.220.172.249,,원격데스크탑,administrator,samanerp1!,설치 X,INTRANET,HPE ProLiant DL360 GEN9,Windows Server 2008 R2,Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz 2.40GHz,32GB,279GB,2.72TB,,,,,,,,,,
|
||||
,,,,,,,,,Remote Util,678-605-383-130,1234아이티!,,,,,,,,,,,,,,,,,,
|
||||
,sa-idc-003,SATIS 01,"구 SATIS 서버, 세금계산서 발행(회계)",서관 204번,,,118.220.172.228,,원격데스크탑,administrator,satissg11707808,설치 X,satis01,HPE ProLiant DL380p GEN8,Windows Server 2008 R2,Intel(R) Xeon(R) CPU E5-2643 0 @ 3.30GHz 3.30GHz,20GB,100GB,458GB,,,,,,,,,,
|
||||
,sa-idc-004,SATIS 02,SATIS 리뉴얼 버전 (ERP 서버),서관 204번,,,118.220.172.229,,원격데스크탑,administrator,satissg11707808,설치 X,satis02,HPE ProLiant DL380p GEN8,Windows Server 2008 R2,Intel(R) Xeon(R) CPU E5-2643 0 @ 3.30GHz 3.30GHz,20GB,100GB,458GB,18.1TB,,,,,,,,,
|
||||
,sa-idc-005,웹 서버,남양주 테스트 서버 (도메인 관리 기능 제거 2026.03.11),서관 204번,,,samanweb.cafe24.com,118.220.172.195,원격데스크탑,administrator,saman+2013+web,"win exp, 포트 안열림",www,HPE ProLiant DL380p GEN8,Windwos Server 2012,Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz 2.40GHz,16GB,100GB,230GB,230GB,,,,,,,,,
|
||||
,sa-idc-006,PQ DB 서버,,서관 204번,,,118.220.172.231,,원격데스크탑,administrator,7013ddj10235!, O,src5dd67f2ed,HPE ProLiant DL360 Gen10,Windows Server 2019,intel xeon silver4210R CPU @2.40GHz 2.39GHZ,32GB,278GB,2.18TB,,20241216 구매교체,삼안,,,,,,,
|
||||
,sa-idc-007,Oracle DB 서버,,서관 202번,,,118.220.172.225,,원격데스크탑,administrator,7013ddj10235!,"win exp, raid X",SAMAN-DB,HPE ProLiant DL380 GEN9,Windows Server 2012,Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz 2.20GHz,64GB,558GB,1.09TB,1.09TB,,,,,,,,,
|
||||
,sa-idc-008,안전관리,"삼안 개발서버2 - AI, SSL, 장헌TBM, 노드",서관 202번,,,1.234.37.171,,원격데스크탑,administrator,samanerp1!,연결 X,,HPE ProLiant DL380 GEN10,Windwos Server 2022,Intel Xeon(R) Silver 4210R CPU @ 2.40GHz,128GB,278GB,3.27TB,,20250410 설치,삼안,,,,,,,
|
||||
,sa-idc-009,가족사 공통메뉴,"삼안 개발서버1 - QNA, 급여명세서",서관 202번,,,118.220.172.233,,원격데스크탑,administrator,samanerp1!,O,srcc9ac928ee,HPE ProLiant DL380 GEN10,Windwos Server 2022,Intel Xeon(R) Silver 4210R CPU @ 2.40GHz,128GB,278GB,3.27TB,,20250410 설치,삼안,,,,,,,
|
||||
한라,hl-idc-001,한라 인트라넷,"인트라넷,안전, 운영, MISO 서버로 운영 중(win 2008)",동관 54번,,,1.234.37.143,,Remote Util,1.234.37.143,1234dkdlxl!,설치 X,,HPE ProLiant DL360 GEN9,Windows Server 2008 R2,Intel(R) Xeon(R) CPU E5-2603 v4 @ 1.70GHz 1.70GHz,8GB,299GB,631GB,,,,,,,,,,
|
||||
,hl-idc-002,안전전산화 서버 (디자인팀 웹),"인트라넷 서버 다운 시 백업용 대기, (임시) 디자인팀 웹 퍼블리싱 서버",동관 54번,,,1.234.37.144,192.168.20.49,Remote Util,1.234.37.144,1234dkdlxl!,O,,HPE ProLiant DL360 GEN9,Windows Server 2012,Intel(R) Xeon(R) CPU E5-2603 v4 @ 1.70GHz 1.70GHz,8GB,299GB,631GB,,,,,,,,,,
|
||||
,hl-idc-003,개발서버2,PTC 연구비로 구매한 예비서버2 ,동관 53번,,,192.168.20.171,1.234.37.171,Remote Util,1.234.37.171,1234dkdlxl!,O,,HPE ProLiant DL380 Gen10,Windows Server 2019 Standard,Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz,32GB,280GB,1TB,,20220921 추정,ptc,,,,,,,
|
||||
,,,"이전 : 하수도자산 소스+프로그램 현재 : 큰길 서비스용 xampp+ PostgreSQL, BEPs",,,,,,원격데스크탑,administrator,Hanmac2141!%,,src775d3e5df,,,,,,,,,,,,,,,,
|
||||
장헌,jh-idc-001,장헌인트라넷,,서관 205번,,,211.206.127.71,192.168.10.6,Remote Util,211.206.127.71,1234dkdlxl!,잠금 걸려있음,,HPE ProLiant DL380 GEN10,Windows Server 2019,Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz 2.39GHz,32GB,280GB,1TB,,20220921 추정,ptc,,,,,,,
|
||||
,jh-idc-002,장헌 인트라넷 예비,,동관 53번,,,1.234.37.170,192.168.20.170,Remote Util,1.234.37.170,1234dkdlxl!,"원격 X, O
|
||||
",,HPE ProLiant DL360 Gen10,Windows Server 2019,Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz 2.39GHz,32GB,280GB,1TB,,20220401 추정,장헌,,,,,,,
|
||||
,,,,,,,,,원격데스크탑,Administrator,Hanmac2141!,,,,,,,,,,,,,,,,,,
|
||||
,jh-idc-003,인트라넷(구),현재는 GIT 백업 으로 사용,서관 205번,,,211.206.127.110,192.168.10.40,Remote Util,211.206.127.110,1234dkdlxl!,,,,Windows Server 2019,Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz,,,,,,,,,,,,,
|
||||
,,,,,,,,,원격데스크탑,User,Hanmac2141!,,,,,,,,,,,,,,,,,,
|
||||
(주)장헌,jh-idc-004,(주) 장헌 인트라넷,2025.12.23 (주) 장헌 센터 MDF에서 IDC로 이전 설치,서관 205번,,,211.206.127.76,,원격데스크탑,User,Hanmac2141!%,"win exp, raid X",DESKTOP-5IL75B7,,Windows 10,12th Gen Intel(R) Core(TM) i7-12700F,32GB,465GB,1.81TB,,,,,,,,,,
|
||||
PTC,ptc-idc-001,PTC인트라넷,"구 파일 서버(부서자료 백업용), 2024.05.22 인트라넷서버로 교체",서관 205번,,,211.206.127.72,192.168.10.7,Remote Util,211.206.127.72,1234dkdlxl!,설치 X,,SYSTEM X3650 M2,Windows Server 2008 R2,Intel(R) Xeon(R) CPU E5520 @ 2.27GHz 2.26GHz,16GB,556GB,,,,,,,,,,,
|
||||
,ptc-idc-002,예비서버,PTC 인트라넷 예비서버,서관 204번,,,192.168.10.8,,원격데스크탑,administrator,1234dkdlxl!,O,,HPE ProLiant DL360 GEN10,Windows Server 2019,Intel Xeon(R) Silver 4210R CPU @ 2.40GHz,32GB,278GB,1.09TB,,20220401 추정,장헌,,,,,,,
|
||||
,ptc-idc-003,DB 백업 서버,"구 파일 인트라넷, 2024.05.22에 DB 백업 테스트 서버로 변경 (데스크탑)",서관 205번,,,211.206.127.74,192.168.10.9,Remote Util,211.206.127.74,1234dkdlxl!,설치 X,,,Window 7,Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz 2.13GHz,4GB,593GB,1.23TB,,,,,,,,,,
|
||||
바론,br-idc-001,인트라넷,,서관 205번,,,211.206.127.75,192.168.10.10,원격데스크탑,administrator,Hanmac2141!%,O,srcf0136042d,HPE ProLiant DL360 GEN10,Windows Server 2022,Intel Xeon(R) Silver 4210R CPU @ 2.40GHz,32GB,280GB,2.18TB,,20250414 추정,바론,,,,,,,
|
||||
현타,ht-idc-001,인트라넷,,동관 53번,,,1.234.37.172,192.168.20.172,원격데스크탑,administrator,Hanmac2141!,O,src901e49933,HPE ProLiant DL380 GEN10,Windows Server 2019,Intel Xeon Silver 4210R CPU @ 2.40GHz 2.39GHz,32GB,280GB,1TB,,20220921 추정,ptc,,,,,,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
스토리지 목록,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
회사,서버번호,구분,비고,설치위치,담당자,,IP 주소,,원격접속,,,,,,모델명,용량,,,,,,,,,,,,,
|
||||
,,,,,정,부,,,접속도구,아이디,비빌번호,,,,,,,,,,,,,,,,,,
|
||||
삼안,sa-das-001,,"Satis01, Satis02 광케이블 연결 (물리연결)",서관 205번,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,sa-nas-001,인트라넷 백업 스토리지,,서관 203번,,,(IDC) 118.220.172.246,,원격,administrator,sg11707808,,,,Promiss R Series,36TB,,,,,,,,,,,,,
|
||||
,sa-nas-002,성과품 스토리지,,서관 205번,,,(IDC) 118.220.172.248,,원격,administrator,sg11707808,,,,ENC_3U_16BAY_D // SEAGATE ST2000NM0045,23TB,,,,,20190603 추정,삼안,,,,,,,
|
||||
,,,매니지먼트 접속 확인 불가 (콘솔 연결 후 페이지 오픈 필요),,,,(매니지먼트) 118.220.172.247,,원격,-,-,,,,,,,,,,,,,,,,,,
|
||||
,sa-nas-003,성과품 백업 스토리지,,서관 202번,,,(IDC) 118.220.172.241,,원격,administrator,saman1!,,,,Promiss R Series,48TB,,,,,20250313,삼안,,,,,,,
|
||||
,,,,,,,(매지니먼트) 118.220.172.240,,원격,admin0,Root1234,,,,,,,,,,,,,,,,,,
|
||||
한라,hl-das-001,,파일서버 정보 없음(접속 불가),동관 54번,,,,,,,,,,,,,,,,,20190701 추정,한라,(한라 파일서버도 동일일자 추정),,,,,,
|
||||
,hl-das-002,,,동관 54번,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
|
1834
build/pc_agent/Analysis-00.toc
Normal file
211
build/pc_agent/EXE-00.toc
Normal file
@@ -0,0 +1,211 @@
|
||||
('D:\\이태훈\\22전산자산조사\\ITAM\\dist\\pc_agent.exe',
|
||||
True,
|
||||
False,
|
||||
False,
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-console.ico',
|
||||
None,
|
||||
False,
|
||||
False,
|
||||
b'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<assembly xmlns='
|
||||
b'"urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\n <trustInfo x'
|
||||
b'mlns="urn:schemas-microsoft-com:asm.v3">\n <security>\n <requested'
|
||||
b'Privileges>\n <requestedExecutionLevel level="asInvoker" uiAccess='
|
||||
b'"false"/>\n </requestedPrivileges>\n </security>\n </trustInfo>\n '
|
||||
b'<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">\n <'
|
||||
b'application>\n <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f'
|
||||
b'0}"/>\n <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>\n '
|
||||
b' <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>\n <s'
|
||||
b'upportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>\n <supporte'
|
||||
b'dOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>\n </application>\n <'
|
||||
b'/compatibility>\n <application xmlns="urn:schemas-microsoft-com:asm.v3">'
|
||||
b'\n <windowsSettings>\n <longPathAware xmlns="http://schemas.micros'
|
||||
b'oft.com/SMI/2016/WindowsSettings">true</longPathAware>\n </windowsSett'
|
||||
b'ings>\n </application>\n <dependency>\n <dependentAssembly>\n <ass'
|
||||
b'emblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version='
|
||||
b'"6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" langua'
|
||||
b'ge="*"/>\n </dependentAssembly>\n </dependency>\n</assembly>',
|
||||
True,
|
||||
False,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\pc_agent.pkg',
|
||||
[('pyi-contents-directory _internal', '', 'OPTION'),
|
||||
('PYZ-00.pyz', 'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\PYZ-00.pyz', 'PYZ'),
|
||||
('struct',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\struct.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod01_archive',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\pyimod01_archive.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod02_importers',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\pyimod02_importers.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod03_ctypes',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\pyimod03_ctypes.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod04_pywin32',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\pyimod04_pywin32.pyc',
|
||||
'PYMODULE'),
|
||||
('pyiboot01_bootstrap',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_inspect',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pkgutil',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_multiprocessing',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_cryptography_openssl',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks\\pyi_rth_cryptography_openssl.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pywintypes',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks\\pyi_rth_pywintypes.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pythoncom',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks\\pyi_rth_pythoncom.py',
|
||||
'PYSOURCE'),
|
||||
('pc_agent', 'D:\\이태훈\\22전산자산조사\\ITAM\\pc_agent.py', 'PYSOURCE'),
|
||||
('python312.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\python312.dll',
|
||||
'BINARY'),
|
||||
('pywin32_system32\\pywintypes312.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\pywin32_system32\\pywintypes312.dll',
|
||||
'BINARY'),
|
||||
('pywin32_system32\\pythoncom312.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\pywin32_system32\\pythoncom312.dll',
|
||||
'BINARY'),
|
||||
('select.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\select.pyd',
|
||||
'EXTENSION'),
|
||||
('_multiprocessing.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_multiprocessing.pyd',
|
||||
'EXTENSION'),
|
||||
('pyexpat.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\pyexpat.pyd',
|
||||
'EXTENSION'),
|
||||
('_ssl.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_ssl.pyd',
|
||||
'EXTENSION'),
|
||||
('_hashlib.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_hashlib.pyd',
|
||||
'EXTENSION'),
|
||||
('unicodedata.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\unicodedata.pyd',
|
||||
'EXTENSION'),
|
||||
('_decimal.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_decimal.pyd',
|
||||
'EXTENSION'),
|
||||
('_lzma.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_lzma.pyd',
|
||||
'EXTENSION'),
|
||||
('_bz2.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_bz2.pyd',
|
||||
'EXTENSION'),
|
||||
('_ctypes.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_ctypes.pyd',
|
||||
'EXTENSION'),
|
||||
('_queue.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_queue.pyd',
|
||||
'EXTENSION'),
|
||||
('_wmi.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_wmi.pyd',
|
||||
'EXTENSION'),
|
||||
('_socket.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_socket.pyd',
|
||||
'EXTENSION'),
|
||||
('_overlapped.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_overlapped.pyd',
|
||||
'EXTENSION'),
|
||||
('_asyncio.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_asyncio.pyd',
|
||||
'EXTENSION'),
|
||||
('_cffi_backend.cp312-win_amd64.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\_cffi_backend.cp312-win_amd64.pyd',
|
||||
'EXTENSION'),
|
||||
('cryptography\\hazmat\\bindings\\_rust.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography\\hazmat\\bindings\\_rust.pyd',
|
||||
'EXTENSION'),
|
||||
('charset_normalizer\\md__mypyc.cp312-win_amd64.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\charset_normalizer\\md__mypyc.cp312-win_amd64.pyd',
|
||||
'EXTENSION'),
|
||||
('charset_normalizer\\md.cp312-win_amd64.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\charset_normalizer\\md.cp312-win_amd64.pyd',
|
||||
'EXTENSION'),
|
||||
('win32\\_win32sysloader.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\win32\\_win32sysloader.pyd',
|
||||
'EXTENSION'),
|
||||
('win32\\win32api.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\win32\\win32api.pyd',
|
||||
'EXTENSION'),
|
||||
('Pythonwin\\win32ui.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\Pythonwin\\win32ui.pyd',
|
||||
'EXTENSION'),
|
||||
('win32\\win32event.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\win32\\win32event.pyd',
|
||||
'EXTENSION'),
|
||||
('win32\\win32trace.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\win32\\win32trace.pyd',
|
||||
'EXTENSION'),
|
||||
('VCRUNTIME140.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\VCRUNTIME140.dll',
|
||||
'BINARY'),
|
||||
('VCRUNTIME140_1.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\VCRUNTIME140_1.dll',
|
||||
'BINARY'),
|
||||
('libssl-3.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\libssl-3.dll',
|
||||
'BINARY'),
|
||||
('libcrypto-3.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\libcrypto-3.dll',
|
||||
'BINARY'),
|
||||
('libffi-8.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\libffi-8.dll',
|
||||
'BINARY'),
|
||||
('python3.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\python3.dll',
|
||||
'BINARY'),
|
||||
('Pythonwin\\mfc140u.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\Pythonwin\\mfc140u.dll',
|
||||
'BINARY'),
|
||||
('certifi\\cacert.pem',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\certifi\\cacert.pem',
|
||||
'DATA'),
|
||||
('certifi\\py.typed',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\certifi\\py.typed',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\licenses\\LICENSE.BSD',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\licenses\\LICENSE.BSD',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\licenses\\LICENSE',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\licenses\\LICENSE',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\RECORD',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\RECORD',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\METADATA',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\METADATA',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\WHEEL',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\WHEEL',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\INSTALLER',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\INSTALLER',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\licenses\\LICENSE.APACHE',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\licenses\\LICENSE.APACHE',
|
||||
'DATA'),
|
||||
('base_library.zip',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\base_library.zip',
|
||||
'DATA')],
|
||||
[],
|
||||
False,
|
||||
False,
|
||||
1779102721,
|
||||
[('run.exe',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\bootloader\\Windows-64bit-intel\\run.exe',
|
||||
'EXECUTABLE')],
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\python312.dll')
|
||||
189
build/pc_agent/PKG-00.toc
Normal file
@@ -0,0 +1,189 @@
|
||||
('D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\pc_agent.pkg',
|
||||
{'BINARY': True,
|
||||
'DATA': True,
|
||||
'EXECUTABLE': True,
|
||||
'EXTENSION': True,
|
||||
'PYMODULE': True,
|
||||
'PYSOURCE': True,
|
||||
'PYZ': False,
|
||||
'SPLASH': True,
|
||||
'SYMLINK': False},
|
||||
[('pyi-contents-directory _internal', '', 'OPTION'),
|
||||
('PYZ-00.pyz', 'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\PYZ-00.pyz', 'PYZ'),
|
||||
('struct',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\struct.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod01_archive',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\pyimod01_archive.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod02_importers',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\pyimod02_importers.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod03_ctypes',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\pyimod03_ctypes.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod04_pywin32',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\localpycs\\pyimod04_pywin32.pyc',
|
||||
'PYMODULE'),
|
||||
('pyiboot01_bootstrap',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_inspect',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pkgutil',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_multiprocessing',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_cryptography_openssl',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks\\pyi_rth_cryptography_openssl.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pywintypes',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks\\pyi_rth_pywintypes.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pythoncom',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks\\pyi_rth_pythoncom.py',
|
||||
'PYSOURCE'),
|
||||
('pc_agent', 'D:\\이태훈\\22전산자산조사\\ITAM\\pc_agent.py', 'PYSOURCE'),
|
||||
('python312.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\python312.dll',
|
||||
'BINARY'),
|
||||
('pywin32_system32\\pywintypes312.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\pywin32_system32\\pywintypes312.dll',
|
||||
'BINARY'),
|
||||
('pywin32_system32\\pythoncom312.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\pywin32_system32\\pythoncom312.dll',
|
||||
'BINARY'),
|
||||
('select.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\select.pyd',
|
||||
'EXTENSION'),
|
||||
('_multiprocessing.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_multiprocessing.pyd',
|
||||
'EXTENSION'),
|
||||
('pyexpat.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\pyexpat.pyd',
|
||||
'EXTENSION'),
|
||||
('_ssl.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_ssl.pyd',
|
||||
'EXTENSION'),
|
||||
('_hashlib.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_hashlib.pyd',
|
||||
'EXTENSION'),
|
||||
('unicodedata.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\unicodedata.pyd',
|
||||
'EXTENSION'),
|
||||
('_decimal.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_decimal.pyd',
|
||||
'EXTENSION'),
|
||||
('_lzma.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_lzma.pyd',
|
||||
'EXTENSION'),
|
||||
('_bz2.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_bz2.pyd',
|
||||
'EXTENSION'),
|
||||
('_ctypes.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_ctypes.pyd',
|
||||
'EXTENSION'),
|
||||
('_queue.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_queue.pyd',
|
||||
'EXTENSION'),
|
||||
('_wmi.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_wmi.pyd',
|
||||
'EXTENSION'),
|
||||
('_socket.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_socket.pyd',
|
||||
'EXTENSION'),
|
||||
('_overlapped.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_overlapped.pyd',
|
||||
'EXTENSION'),
|
||||
('_asyncio.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\_asyncio.pyd',
|
||||
'EXTENSION'),
|
||||
('_cffi_backend.cp312-win_amd64.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\_cffi_backend.cp312-win_amd64.pyd',
|
||||
'EXTENSION'),
|
||||
('cryptography\\hazmat\\bindings\\_rust.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography\\hazmat\\bindings\\_rust.pyd',
|
||||
'EXTENSION'),
|
||||
('charset_normalizer\\md__mypyc.cp312-win_amd64.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\charset_normalizer\\md__mypyc.cp312-win_amd64.pyd',
|
||||
'EXTENSION'),
|
||||
('charset_normalizer\\md.cp312-win_amd64.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\charset_normalizer\\md.cp312-win_amd64.pyd',
|
||||
'EXTENSION'),
|
||||
('win32\\_win32sysloader.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\win32\\_win32sysloader.pyd',
|
||||
'EXTENSION'),
|
||||
('win32\\win32api.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\win32\\win32api.pyd',
|
||||
'EXTENSION'),
|
||||
('Pythonwin\\win32ui.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\Pythonwin\\win32ui.pyd',
|
||||
'EXTENSION'),
|
||||
('win32\\win32event.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\win32\\win32event.pyd',
|
||||
'EXTENSION'),
|
||||
('win32\\win32trace.pyd',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\win32\\win32trace.pyd',
|
||||
'EXTENSION'),
|
||||
('VCRUNTIME140.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\VCRUNTIME140.dll',
|
||||
'BINARY'),
|
||||
('VCRUNTIME140_1.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\VCRUNTIME140_1.dll',
|
||||
'BINARY'),
|
||||
('libssl-3.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\libssl-3.dll',
|
||||
'BINARY'),
|
||||
('libcrypto-3.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\libcrypto-3.dll',
|
||||
'BINARY'),
|
||||
('libffi-8.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\libffi-8.dll',
|
||||
'BINARY'),
|
||||
('python3.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\python3.dll',
|
||||
'BINARY'),
|
||||
('Pythonwin\\mfc140u.dll',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\Pythonwin\\mfc140u.dll',
|
||||
'BINARY'),
|
||||
('certifi\\cacert.pem',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\certifi\\cacert.pem',
|
||||
'DATA'),
|
||||
('certifi\\py.typed',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\certifi\\py.typed',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\licenses\\LICENSE.BSD',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\licenses\\LICENSE.BSD',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\licenses\\LICENSE',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\licenses\\LICENSE',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\RECORD',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\RECORD',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\METADATA',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\METADATA',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\WHEEL',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\WHEEL',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\INSTALLER',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\INSTALLER',
|
||||
'DATA'),
|
||||
('cryptography-45.0.2.dist-info\\licenses\\LICENSE.APACHE',
|
||||
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\cryptography-45.0.2.dist-info\\licenses\\LICENSE.APACHE',
|
||||
'DATA'),
|
||||
('base_library.zip',
|
||||
'D:\\이태훈\\22전산자산조사\\ITAM\\build\\pc_agent\\base_library.zip',
|
||||
'DATA')],
|
||||
'python312.dll',
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
[],
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
BIN
build/pc_agent/PYZ-00.pyz
Normal file
1193
build/pc_agent/PYZ-00.toc
Normal file
BIN
build/pc_agent/base_library.zip
Normal file
BIN
build/pc_agent/localpycs/pyimod01_archive.pyc
Normal file
BIN
build/pc_agent/localpycs/pyimod02_importers.pyc
Normal file
BIN
build/pc_agent/localpycs/pyimod03_ctypes.pyc
Normal file
BIN
build/pc_agent/localpycs/pyimod04_pywin32.pyc
Normal file
BIN
build/pc_agent/localpycs/struct.pyc
Normal file
BIN
build/pc_agent/pc_agent.pkg
Normal file
58
build/pc_agent/warn-pc_agent.txt
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
This file lists modules PyInstaller was not able to find. This does not
|
||||
necessarily mean these modules are required for running your program. Both
|
||||
Python's standard library and 3rd-party Python packages often conditionally
|
||||
import optional modules, some of which may be available only on certain
|
||||
platforms.
|
||||
|
||||
Types of import:
|
||||
* top-level: imported at the top-level - look at these first
|
||||
* conditional: imported within an if-statement
|
||||
* delayed: imported within a function
|
||||
* optional: imported within a try-except-statement
|
||||
|
||||
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
|
||||
tracking down the missing module yourself. Thanks!
|
||||
|
||||
missing module named pwd - imported by posixpath (delayed, conditional, optional), shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional), netrc (delayed, conditional), getpass (delayed)
|
||||
missing module named grp - imported by shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional)
|
||||
missing module named _posixsubprocess - imported by subprocess (conditional), multiprocessing.util (delayed)
|
||||
missing module named fcntl - imported by subprocess (optional)
|
||||
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
|
||||
missing module named _scproxy - imported by urllib.request (conditional)
|
||||
missing module named termios - imported by getpass (optional)
|
||||
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||
missing module named posix - imported by os (conditional, optional), posixpath (optional), shutil (conditional), importlib._bootstrap_external (conditional)
|
||||
missing module named resource - imported by posix (top-level)
|
||||
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
|
||||
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
|
||||
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||
missing module named pyimod02_importers - imported by C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgutil.py (delayed)
|
||||
missing module named collections.Callable - imported by collections (optional), socks (optional)
|
||||
missing module named vms_lib - imported by platform (delayed, optional)
|
||||
missing module named 'java.lang' - imported by platform (delayed, optional)
|
||||
missing module named java - imported by platform (delayed)
|
||||
missing module named _winreg - imported by platform (delayed, optional)
|
||||
missing module named simplejson - imported by requests.compat (conditional, optional)
|
||||
missing module named dummy_threading - imported by requests.cookies (optional)
|
||||
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
|
||||
missing module named annotationlib - imported by typing_extensions (conditional)
|
||||
missing module named 'h2.events' - imported by urllib3.http2.connection (top-level)
|
||||
missing module named 'h2.connection' - imported by urllib3.http2.connection (top-level)
|
||||
missing module named h2 - imported by urllib3.http2.connection (top-level)
|
||||
missing module named zstandard - imported by urllib3.util.request (optional), urllib3.response (optional)
|
||||
missing module named brotli - imported by urllib3.util.request (optional), urllib3.response (optional)
|
||||
missing module named brotlicffi - imported by urllib3.util.request (optional), urllib3.response (optional)
|
||||
missing module named win_inet_pton - imported by socks (conditional, optional)
|
||||
missing module named bcrypt - imported by cryptography.hazmat.primitives.serialization.ssh (optional)
|
||||
missing module named cryptography.x509.UnsupportedExtension - imported by cryptography.x509 (optional), urllib3.contrib.pyopenssl (optional)
|
||||
missing module named 'OpenSSL.crypto' - imported by urllib3.contrib.pyopenssl (delayed, conditional)
|
||||
missing module named OpenSSL - imported by urllib3.contrib.pyopenssl (top-level)
|
||||
missing module named 'pyodide.ffi' - imported by urllib3.contrib.emscripten.fetch (delayed, optional)
|
||||
missing module named pyodide - imported by urllib3.contrib.emscripten.fetch (top-level)
|
||||
missing module named js - imported by urllib3.contrib.emscripten.fetch (top-level)
|
||||
missing module named 'win32com.gen_py' - imported by win32com (conditional, optional)
|
||||
16542
build/pc_agent/xref-pc_agent.html
Normal file
24
create_db.js
@@ -1,24 +0,0 @@
|
||||
import * as XLSX from 'xlsx';
|
||||
|
||||
const hwTabs = ['개인PC', '서버', '스토리지', '전산비품'];
|
||||
const swTabs = ['구독SW', '영구SW'];
|
||||
|
||||
const hwHeaders = ['법인', '자산코드', '명칭', '위치', '관리자', 'IP주소', 'MACaddress', 'HW사양', 'OS'];
|
||||
const swHeaders = ['법인', 'SW명', '라이선스키', '할당자', '사용기간', '비고'];
|
||||
|
||||
const wb = XLSX.utils.book_new();
|
||||
|
||||
hwTabs.forEach((tab, i) => {
|
||||
const wsData = [hwHeaders, [`(주)회사${i}`, `ASSET-${i}00`, `${tab} 모델A`, '본사 1층', '관리자A', '192.168.0.1', '00:00:00:00:00:01', 'Core i7, 16GB RAM', 'Windows 10']];
|
||||
const ws = XLSX.utils.aoa_to_sheet(wsData);
|
||||
XLSX.utils.book_append_sheet(wb, ws, tab);
|
||||
});
|
||||
|
||||
swTabs.forEach((tab, i) => {
|
||||
const wsData = [swHeaders, [`(주)회사${i}`, `${tab} Adobe CC`, '1234-5678-ABCD', '홍길동,김철수', '2024.01~2024.12', '본사 전용']];
|
||||
const ws = XLSX.utils.aoa_to_sheet(wsData);
|
||||
XLSX.utils.book_append_sheet(wb, ws, tab);
|
||||
});
|
||||
|
||||
XLSX.writeFile(wb, 'temp_db.xlsx');
|
||||
console.log('temp_db.xlsx created!');
|
||||
45
docs/issues/issue_dashboard_and_modal_optimization.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# [Issue] 소프트웨어 자산 관리 체계 개편 및 클라우드(Cloud) 서비스 관리 신설
|
||||
|
||||
## 1. 개요
|
||||
기존의 단일 소프트웨어(SW) 분류 체계를 비즈니스 모델에 맞춰 **구독형, 영구형, 클라우드형**으로 삼원화하고, 특히 비용 변동이 잦은 클라우드 서비스를 독립적으로 관리할 수 있는 전용 시스템을 신설함.
|
||||
|
||||
---
|
||||
|
||||
## 2. 주요 작업 내용
|
||||
|
||||
### 📂 소프트웨어 관리 프레임워크 재구조화
|
||||
- **분류 체계 개편**: 소프트웨어를 아래 세 가지 유형으로 재정의하여 관리 효율성을 높임.
|
||||
1. **구독형 (Subscription)**: 연/월 정액제로 운영되는 SW
|
||||
2. **영구형 (Perpetual)**: 구매 후 영구 소유하는 SW (유지보수 중심 관리)
|
||||
3. **클라우드형 (Cloud)**: 플랫폼 기반 종량제(AWS, Azure 등) 서비스
|
||||
- **내비게이션 통합**: 상단 탭을 유형별로 분리하여 각 자산 특성에 맞는 리스트 뷰를 제공함.
|
||||
|
||||
### ☁️ 클라우드(Cloud) 서비스 관리 페이지 신설
|
||||
- **전용 리스트 뷰 (`CloudListView.ts`)**:
|
||||
- 플랫폼명, 담당 부서, 프로젝트(사용용도), 결제 수단, 결제일 등 클라우드 특화 항목 중심의 테이블 구성함.
|
||||
- **결제수단별 필터링 기능** (법인카드, 인보이스) 및 통합 검색 기능을 추가함.
|
||||
- **클라우드 전문 모달 (`CloudModal.ts`)**:
|
||||
- 클라우드 요금 및 결제 정보 입력을 위한 2분할 레이아웃 배치함.
|
||||
- **업데이트 이력(History Logs)** 시스템을 도입하여 매월 변동되는 비용을 히스토리 형식으로 기록/추적 가능하게 함.
|
||||
|
||||
### 📊 대시보드(Dashboard) 리팩토링 및 고도화
|
||||
- **카드 레이아웃 최적화**: 사용율, 만료 예정, 클라우드 현황(전월/당월 비교) 정보를 2열 그리드로 정돈함.
|
||||
- **데이터 시각화**:
|
||||
- **클라우드 결제 규모 추이**: 최근 4개월간의 비용 변동을 꺾은선 그래프로 구현함.
|
||||
- **실시간 데이터 연동**: 자산 업데이트 이력(Logs)에 기록된 비용이 대시보드 차트에 실시간 합산 반영되도록 로그 분석 엔진을 구축함.
|
||||
- **상세 팝업 연동**: 대시보드 요약 카드를 클릭하면 해당하는 자산의 상세 목록이 뜨는 모달 연동 기능을 추가함.
|
||||
|
||||
### 🪟 UX 및 데이터 정합성 강화
|
||||
- **수정 저장 워크플로우 (Edit-to-Save)**: 실수로 인한 데이터 변경을 막기 위해 모든 상세 모달에 '조회 모드'를 기본으로 하고, [수정] 버튼 클릭 시에만 입력이 활성화되도록 제어함.
|
||||
- **금액 자동 포맷팅**: 콤마 표시 오류를 해결하고 천 단위 포맷팅을 표준화함.
|
||||
- **결제 임박 알림**: 각 서비스의 결제일을 계산하여 14일 이내 결제가 필요한 항목을 대시보드에서 즉시 파악할 수 있게 함.
|
||||
|
||||
---
|
||||
|
||||
## 3. 향후 과제
|
||||
- 클라우드 플랫폼 간 비용 비교 통계 기능 확장 검토
|
||||
- 결제 수단(법인카드) 만료일에 기초한 알림 서비스 추가 검토
|
||||
|
||||
---
|
||||
**작업자**: Antigravity (AI Assistant)
|
||||
**상태**: 완료 (2026-04-17)
|
||||
33
docs/issues/issue_sw_modal_refactor.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# [이슈] S/W 자산 관리 고도화 및 이력 추적 기능 구현
|
||||
|
||||
## 1. 개요
|
||||
소프트웨어 자산의 라이프사이클을 체계적으로 관리하기 위해 상세 정보 모달을 개편하고, 갱신(업데이트) 이력을 추적할 수 있는 기능을 구현하였습니다. 또한, 사용자의 가독성을 위해 상태를 나타내는 자동 뱃지를 도입하고 날짜 입력 편의성을 개선하였습니다.
|
||||
|
||||
## 2. 작업 상세 내용
|
||||
|
||||
### A. S/W 목록(Table) 개선
|
||||
- **상태 자동 계산 시스템 도입**:
|
||||
- 구독 S/W: 만료일 기준 **[사용중] / [만료]** 자동 표시.
|
||||
- 영구 S/W: 유지보수 대상 여부에 따라 **[유효] / [없음]** 표시.
|
||||
- **UI 뱃지 적용**: 테이블 좌측에 상태 뱃지를 추가하여 시각적 인지도를 높임.
|
||||
|
||||
### B. 상세 정보 모달 개편 (`SWModal.ts`)
|
||||
- **2단 분할 레이아웃 적용**: 좌측(기본 정보), 우측(업데이트 타임라인)으로 UI 재설계.
|
||||
- **날짜 입력 필드 개선**:
|
||||
- '구매일' 필드에 캘린더 피커(Calendar Picker) 적용.
|
||||
- '구독 기간' 필드를 **시작일**과 **종료일**로 분리하여 각각 캘린더 적용.
|
||||
- 직접 입력("yyyy-mm-dd") 형식도 동시 지원.
|
||||
|
||||
### C. 계약 업데이트(갱신) 관리 기능
|
||||
- **[업데이트 추가]** 버튼 및 전용 서브 팝업 구현.
|
||||
- 갱신 시 발생하는 비용, 기간 연장, 메모를 기록하여 타임라인(Log)에 누적.
|
||||
- 업데이트 반영 시 메인 자산 정보의 구독 기한 및 누적 금액이 자동으로 최신화되도록 연동.
|
||||
|
||||
## 3. 관련 파일
|
||||
- `src/views/SW_Table.ts`: 테이블 상태 로직 및 뱃지 렌더링.
|
||||
- `src/components/Modal/SWModal.ts`: 모달 UI 및 날짜 처리, 업데이트 로직.
|
||||
- `src/styles/modal.css`: 분할 레이아웃 및 타임라인 스타일.
|
||||
|
||||
## 4. 확인 사항
|
||||
- 엑셀 업로드/다운로드 시 기존 '구독일' 문자열 형식과의 호환성 유지 확인.
|
||||
- 브라우저 테스트를 통한 캘린더 작동 및 테이블 상태 연동 확인 완료.
|
||||
64
docs/plans/ITAM_RMM_Integration_Plan.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# [보고서] IT 자산 실시간 통합 관리 시스템(RMM) 도입 계획서
|
||||
|
||||
## 1. 도입 배경 및 목적
|
||||
- **현황**: 현재 시스템은 수동 입력 기반의 정적 자산 대장으로 운영되어, 실제 장비의 가동 상태나 장애 여부를 실시간으로 파악하는 데 한계가 있음.
|
||||
- **목적**: 전산자산(서버, PC)의 실시간 상태 정보를 자동 수집하고 장애 징후를 사전에 탐지하여, 선제적 유지보수 체계를 구축하고 운영 효율성을 극대화함.
|
||||
|
||||
## 2. 시스템 주요 기능
|
||||
### 2.1 실시간 가동 상태 모니터링
|
||||
- 주요 자원(CPU, Memory, Disk) 사용률 실시간 수집
|
||||
- 운영체제(OS) 및 주요 시스템 서비스의 정상 작동 여부 확인
|
||||
- 자산 리스트 내 상태 인디케이터(정상/주의/장애) 표시
|
||||
|
||||
### 2.2 원격 제어 및 지원 통합
|
||||
- **기술적 구현 방식 (원클릭 자동 연결)**: 웹사이트에서 전화번호를 누르면 전화 앱이 켜지거나, 이메일 주소를 누르면 메일 창이 뜨는 것과 동일한 원리인 'URL 프로토콜 핸들러' 기술을 적용함.
|
||||
- **자동화 프로세스**: 관리자가 화면의 [연결] 버튼을 클릭하면, 시스템이 팀뷰어나 애니데스크에 "A장비로 연결해줘"라는 신호를 직접 보냄.
|
||||
- **편의성**: 관리자가 대상 장비의 ID나 비밀번호를 직접 복사해서 프로그램에 입력할 필요 없이, 클릭 한 번으로 내 PC에 설치된 원격 소프트웨어가 자동 실행되며 즉시 화면이 연결되도록 구현함.
|
||||
- **유연한 접속 모드 지원**:
|
||||
- **무인 접속(Unattended Access)**: 서버 및 공용 장비의 경우, 사전에 등록된 자격 증명을 통해 관리자 승인만으로 즉시 접속하여 야간 또는 긴급 장애에 대응함.
|
||||
- **사용자 승인 접속(Attended Access)**: 개인용 PC의 경우, 사용자의 화면에 접속 요청 팝업을 띄우고 승인 시에만 화면 공유를 시작하여 개인정보 보호 및 보안 규정을 준수함.
|
||||
- **보안 및 감사 로그 자동화**:
|
||||
- 원격 접속이 시작되는 시점에 관리자 정보, 접속 목적, 대상 장비 정보를 DB에 자동 기록함.
|
||||
- 세션 종료 후 총 작업 시간 및 조치 내역을 입력하도록 유도하여 투명한 유지보수 이력을 관리함.
|
||||
|
||||
### 2.3 원격 지원 상세 워크플로우 (Remote Support Workflow)
|
||||
관리자가 장애를 인지하고 조치를 완료하기까지의 표준 프로세스는 다음과 같습니다.
|
||||
|
||||
1. **지원 요청 및 대상 선택**: 관리자가 ITAM 대시보드 또는 리스트에서 장애가 발생한 자산을 선택하고 '원격 지원 시작' 버튼을 클릭함.
|
||||
2. **접속 모드 자동 판별**:
|
||||
- **서버(무인)**: 시스템이 저장된 자격 증명을 확인하고 관리자에게 '즉시 연결' 팝업을 띄움.
|
||||
- **PC(유인)**: 관리자가 '접속 요청' 버튼을 누르면, 대상 PC 화면에 "관리자가 원격 제어를 요청했습니다. 승인하시겠습니까?" 팝업이 전송됨.
|
||||
3. **세션 초기화 및 로그 생성**: 접속 시도가 승인되면 서버는 즉시 [접속 일시, 관리자 ID, 대상 자산 번호]를 포함한 '세션 로그'를 생성하고 상태를 '진행 중'으로 변경함.
|
||||
4. **프로토콜 핸들러 실행**: 브라우저가 관리자 PC의 원격 제어 앱(TeamViewer 등)을 자동으로 실행하며, 대상 장비의 ID와 패스워드 정보를 암호화된 인자로 전달하여 즉시 화면이 연결됨.
|
||||
5. **조치 및 지원 수행**: 관리자가 실시간으로 장비를 제어하여 장애를 복구함.
|
||||
6. **세션 종료 및 결과 기록**:
|
||||
- 관리자가 원격 제어 앱을 종료하면, ITAM 웹 화면에 '조치 결과 입력' 창이 활성화됨.
|
||||
- 관리자가 조치 내용(예: 서비스 재시작, 패치 적용 등)을 입력하고 저장하면 세션 로그가 최종 확정됨.
|
||||
7. **이력 보관**: 완료된 모든 이력은 '자산 상세 정보 > 유지보수 이력' 탭에서 언제든지 열람 및 보고서 출력이 가능함.
|
||||
|
||||
### 3.3 장애 사전 탐지 및 알림
|
||||
- 설정된 임계치(예: 디스크 잔량 10% 미만) 초과 시 즉시 알림 발송
|
||||
- 장기 미접속 또는 점검 누락 장비의 실시간 식별
|
||||
|
||||
## 3. 운영 프로세스 및 메커니즘
|
||||
1. **데이터 수집 (Collection)**: 각 자산에 배치된 에이전트가 시스템 정보를 주기적으로 추출함.
|
||||
2. **분석 및 판별 (Analysis)**: 수집된 데이터를 중앙 서버에서 분석하여 장비의 상태 등급을 판정함.
|
||||
3. **가시화 (Visualization)**: 통합 관리 대시보드를 통해 전체 자산의 헬스 상태를 실시간으로 출력함.
|
||||
4. **대응 (Action)**: 장애 감지 시 원격 제어 기능을 호출하여 즉각적인 기술 지원을 수행함.
|
||||
|
||||
## 4. 핵심 기술 및 도구
|
||||
- **에이전트**: PowerShell 기반의 경량 스크립트를 활용하여 별도의 상용 소프트웨어 설치 없이 시스템 정보 수집.
|
||||
- **백엔드**: Node.js 환경에서 대용량 점검 데이터를 효율적으로 처리하고 데이터베이스화함.
|
||||
- **프론트엔드**: TypeScript를 활용하여 직관적이고 반응성이 뛰어난 관리자 대시보드 구현.
|
||||
- **원격 솔루션**: 보안성이 검증된 TeamViewer/AnyDesk의 프로토콜 연동을 통한 안전한 원격 접속 환경 구축.
|
||||
|
||||
## 5. 기대 효과
|
||||
- **가용성 증대**: 장애 발생 전 사전 조치를 통해 시스템 다운타임을 최소화하고 업무 연속성 확보.
|
||||
- **비용 절감**: 현장 방문 점검 최소화 및 원격 조치를 통한 IT 운영 관리 비용 및 시간 절감.
|
||||
- **데이터 기반 의무**: 객관적인 성능 지표 및 점검 이력을 바탕으로 정밀한 자산 교체 주기 산정 및 감사 대응.
|
||||
- **관리 생산성 향상**: 자산 정보 조회와 실시간 관리를 단일 플랫폼으로 통합하여 업무 프로세스 간소화.
|
||||
|
||||
## 6. 향후 계획
|
||||
- 1단계: 서버 자산 중심의 실시간 모니터링 및 대시보드 구축
|
||||
- 2단계: 전사 PC 대상 원격 지원 및 보안 점검 기능 확대 적용
|
||||
- 3단계: 누적 데이터를 활용한 성능 분석 및 월간 운영 보고서 자동화
|
||||
318
docs/plans/IT_Asset_RMM_System_Report_Detailed.md
Normal file
@@ -0,0 +1,318 @@
|
||||
# 전산자산 원격 점검 및 관리 시스템(RMM) 구축 조사 보고서 (상세판)
|
||||
|
||||
## 1. RMM(Remote Monitoring & Management) 개요
|
||||
|
||||
RMM(Remote Monitoring & Management)은 서버, 업무용 PC, 노트북 등 IT 자산에 에이전트를 설치하여
|
||||
중앙 관리 서버에서 상태를 자동 수집하고, 이상 발생 시 경고를 발송하며, 필요 시 원격 접속으로 문제를 해결하는
|
||||
기업용 IT 운영 관리 체계입니다.
|
||||
|
||||
### 주요 기능
|
||||
- CPU, 메모리, 디스크 상태 모니터링
|
||||
- Windows 서비스 및 프로세스 상태 점검
|
||||
- OS 패치 및 백신 상태 확인
|
||||
- 자동 점검 스케줄링 (1일 1~2회 이상)
|
||||
- 이상 발생 시 이메일/메신저 알림
|
||||
- 원격 접속을 통한 장애 조치
|
||||
- 점검 이력 및 감사 로그 보관
|
||||
|
||||
---
|
||||
|
||||
## 2. 구축 목표
|
||||
|
||||
### 서버 및 서버용 PC
|
||||
- 하루 1~2회 자동 점검
|
||||
- 주요 시스템 자원 및 서비스 상태 수집
|
||||
- 이상 발생 시 관리자 즉시 통보
|
||||
|
||||
### 업무용 PC
|
||||
- 중앙 관리 서버에서 정기 점검
|
||||
- 패치 및 보안 상태 확인
|
||||
|
||||
### 개인 PC
|
||||
- 사용자가 직접 점검 실행
|
||||
- 결과를 중앙 서버에 업로드
|
||||
|
||||
### 관리자
|
||||
- 마지막 점검 일시 확인
|
||||
- 성공/실패 여부 확인
|
||||
- 미실행 장비 식별
|
||||
- 필요 시 즉시 원격 접속
|
||||
|
||||
---
|
||||
|
||||
## 3. 기대 효과
|
||||
|
||||
- 장애 조기 탐지 및 사전 예방
|
||||
- 현장 방문 최소화
|
||||
- 점검 누락 방지
|
||||
- 감사 대응 자료 자동 확보
|
||||
- 자산 운영 현황 실시간 가시화
|
||||
- 사용자 점검 이행 여부 관리
|
||||
|
||||
---
|
||||
|
||||
## 4. 전체 시스템 아키텍처
|
||||
|
||||
```text
|
||||
[관리자 웹 포털]
|
||||
├─ 대시보드
|
||||
├─ 점검 결과 조회
|
||||
├─ 원격 접속 버튼
|
||||
├─ 알림 관리
|
||||
└─ 사용자 수행 현황
|
||||
|
||||
│
|
||||
▼
|
||||
|
||||
[중앙 관리 서버]
|
||||
├─ 스케줄러
|
||||
├─ 데이터 수집 API
|
||||
├─ 분석 엔진
|
||||
├─ 알림 시스템
|
||||
└─ 데이터베이스
|
||||
|
||||
│
|
||||
▼
|
||||
|
||||
[에이전트 설치 대상]
|
||||
├─ 서버
|
||||
├─ 서버용 PC
|
||||
├─ 업무용 PC
|
||||
└─ 개인 PC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 주요 구성 요소
|
||||
|
||||
### 5.1 중앙 관리 서버
|
||||
- 스케줄 실행
|
||||
- 상태 분석
|
||||
- 데이터 저장
|
||||
- 알림 전송
|
||||
- 웹 서비스 제공
|
||||
|
||||
### 5.2 에이전트 프로그램
|
||||
- PowerShell 또는 Python 기반
|
||||
- 상태 수집
|
||||
- 중앙 서버 전송
|
||||
|
||||
### 5.3 관리자 웹 대시보드
|
||||
- 실시간 현황 조회
|
||||
- 점검 이력 확인
|
||||
- 원격 접속 실행
|
||||
|
||||
### 5.4 원격 접속 솔루션
|
||||
- TeamViewer Tensor
|
||||
- AnyDesk
|
||||
- Microsoft Remote Help
|
||||
|
||||
### 5.5 데이터베이스
|
||||
- SQL Server 또는 PostgreSQL
|
||||
|
||||
### 5.6 알림 시스템
|
||||
- 이메일
|
||||
- Microsoft Teams
|
||||
- Slack
|
||||
|
||||
---
|
||||
|
||||
## 6. 점검 항목
|
||||
|
||||
### 공통 점검 항목
|
||||
- CPU 사용률
|
||||
- 메모리 사용률
|
||||
- 디스크 여유 공간
|
||||
- 네트워크 연결 상태
|
||||
- 시스템 부팅 시간
|
||||
- 재부팅 필요 여부
|
||||
|
||||
### 서버 추가 항목
|
||||
- 주요 서비스 실행 여부
|
||||
- 이벤트 로그 오류
|
||||
- 백업 결과
|
||||
- DB 상태
|
||||
|
||||
### PC 추가 항목
|
||||
- 백신 업데이트 여부
|
||||
- Windows Update 상태
|
||||
- BitLocker 상태
|
||||
|
||||
### 개인 PC
|
||||
- 기본 시스템 상태
|
||||
- 점검 수행 여부 및 시간 기록
|
||||
|
||||
---
|
||||
|
||||
## 7. 운영 프로세스
|
||||
|
||||
### 정상 운영
|
||||
1. 스케줄러가 하루 1~2회 자동 실행
|
||||
2. 에이전트가 점검 수행
|
||||
3. 결과를 중앙 서버로 전송
|
||||
4. 분석 엔진이 정상 여부 판정
|
||||
5. 대시보드에 저장
|
||||
|
||||
### 이상 발생 시
|
||||
1. 임계치 초과 또는 서비스 중지 감지
|
||||
2. 관리자에게 알림 발송
|
||||
3. 관리자가 원격 접속
|
||||
4. 조치 내용 기록
|
||||
|
||||
### 개인 PC
|
||||
1. 사용자가 '점검 실행' 버튼 클릭
|
||||
2. 스크립트 수행
|
||||
3. 결과 업로드
|
||||
4. 관리자가 이행 여부 확인
|
||||
|
||||
---
|
||||
|
||||
## 8. 개인 PC 자가 점검 기능
|
||||
|
||||
### 사용자 화면
|
||||
- 점검 실행 버튼
|
||||
- 결과 요약 표시
|
||||
- 마지막 점검 시간 표시
|
||||
|
||||
### 관리자 확인 항목
|
||||
- 마지막 점검 일시
|
||||
- 성공/실패 여부
|
||||
- 미실행 기간
|
||||
- 이상 발생 내역
|
||||
|
||||
---
|
||||
|
||||
## 9. 관리자 대시보드 구성
|
||||
|
||||
- 전체 자산 현황
|
||||
- 정상/경고/장애 통계
|
||||
- 최근 점검 성공률
|
||||
- 미점검 장비 목록
|
||||
- 개인 PC 수행 현황
|
||||
- 원격 접속 바로가기
|
||||
- 월간 보고서
|
||||
|
||||
---
|
||||
|
||||
## 10. 솔루션 비교
|
||||
|
||||
| 솔루션 | 특징 | 적합도 |
|
||||
|------|------|------|
|
||||
| Microsoft Intune | 엔드포인트 관리 및 규정 준수 | 매우 높음 |
|
||||
| TeamViewer Tensor | 기업용 원격 접속 및 RMM 연동 | 매우 높음 |
|
||||
| ManageEngine Endpoint Central | 자산, 패치, 원격 관리 통합 | 매우 높음 |
|
||||
| Zabbix | 오픈소스 모니터링 | 높음 |
|
||||
| Splashtop Remote Support | 원격 지원 + RMM | 높음 |
|
||||
| Power BI | 대시보드 및 보고 | 매우 높음 |
|
||||
|
||||
---
|
||||
|
||||
## 11. 권장 구축 방안
|
||||
|
||||
### 권장 아키텍처
|
||||
- Microsoft Intune
|
||||
- TeamViewer Tensor
|
||||
- PowerShell 자동 점검 스크립트
|
||||
- Microsoft SQL Server
|
||||
- Power BI
|
||||
- Microsoft Teams 알림
|
||||
|
||||
### 권장 이유
|
||||
- Windows 환경과 높은 호환성
|
||||
- 보안 및 감사 기능 우수
|
||||
- 사용자 PC까지 통합 관리 가능
|
||||
- 경영진 보고 자동화 가능
|
||||
|
||||
---
|
||||
|
||||
## 12. 보안 요구사항
|
||||
|
||||
- MFA(다중 인증)
|
||||
- RBAC(역할 기반 권한 관리)
|
||||
- TLS 암호화
|
||||
- 감사 로그 저장
|
||||
- 승인된 관리자만 원격 접속
|
||||
- 사용자 동의 기반 개인 PC 점검
|
||||
|
||||
---
|
||||
|
||||
## 13. 구축 일정 (예시)
|
||||
|
||||
| 단계 | 기간 |
|
||||
|------|------|
|
||||
| 요구사항 분석 | 2주 |
|
||||
| 솔루션 선정 | 2주 |
|
||||
| PoC | 4주 |
|
||||
| 설계 및 개발 | 6주 |
|
||||
| 시범 운영 | 4주 |
|
||||
| 전사 확대 | 4주 |
|
||||
|
||||
총 예상 기간: 약 4~6개월
|
||||
|
||||
---
|
||||
|
||||
## 14. 예상 비용 (예시)
|
||||
|
||||
| 항목 | 비용 수준 |
|
||||
|------|----------|
|
||||
| Intune 라이선스 | 사용자당 월 과금 |
|
||||
| TeamViewer Tensor | 동시 세션 기준 |
|
||||
| 개발 비용 | 중~고 |
|
||||
| 운영 비용 | 중간 |
|
||||
|
||||
---
|
||||
|
||||
## 15. 구축 우선순위
|
||||
|
||||
### 1단계
|
||||
- 핵심 서버 모니터링
|
||||
- 관리자 대시보드
|
||||
|
||||
### 2단계
|
||||
- 원격 접속 통합
|
||||
- 자동 알림
|
||||
|
||||
### 3단계
|
||||
- 개인 PC 자가 점검
|
||||
|
||||
### 4단계
|
||||
- Power BI 경영 보고
|
||||
|
||||
---
|
||||
|
||||
## 16. 최종 권장안
|
||||
|
||||
> Microsoft Intune + TeamViewer Tensor + PowerShell + SQL Server + Power BI
|
||||
|
||||
이 조합은 다음 요구사항을 모두 충족합니다.
|
||||
- 자동 점검
|
||||
- 이상 탐지
|
||||
- 원격 접속
|
||||
- 사용자 자가 점검
|
||||
- 이력 관리
|
||||
- 감사 대응
|
||||
- 경영진 보고
|
||||
|
||||
---
|
||||
|
||||
## 17. 공식 출처 및 링크
|
||||
|
||||
- Microsoft Intune: https://intune.microsoft.com
|
||||
- TeamViewer Tensor: https://www.teamviewer.com/en/tensor/
|
||||
- TeamViewer RMM 소개: https://www.teamviewer.com/en/solutions/use-cases/rmm-remote-monitoring-management/
|
||||
- ManageEngine Endpoint Central: https://www.manageengine.com/products/endpoint-central/
|
||||
- Zabbix: https://www.zabbix.com
|
||||
- Power BI: https://powerbi.microsoft.com
|
||||
- Microsoft SQL Server: https://www.microsoft.com/sql-server
|
||||
- Splashtop RMM 설명: https://www.splashtop.com/blog/what-is-remote-monitoring-and-management
|
||||
|
||||
---
|
||||
|
||||
## 18. 결론
|
||||
|
||||
본 시스템은 서버, 업무용 PC, 개인 PC를 통합 관리하여
|
||||
정기적인 자동 점검과 이상 탐지, 원격 접속, 사용자 자가 점검, 점검 이력 관리까지 지원하는
|
||||
기업용 IT 운영 플랫폼입니다.
|
||||
|
||||
특히 개인 PC의 자가 점검 기능과 관리자 추적 기능을 포함함으로써
|
||||
규정 준수와 운영 효율성을 동시에 확보할 수 있습니다.
|
||||
379
docs/plans/PC_사양_개선_기획서.html
Normal file
@@ -0,0 +1,379 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=device-width, initial-scale=1.0">
|
||||
<title>PC 사양 대시보드 시각화 개선 기획서</title>
|
||||
<!-- Google Fonts: Pretendard 대체용 Outfit & Noto Sans KR -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700;900&family=Outfit:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--primary: #4F46E5;
|
||||
--primary-light: #EEF2FF;
|
||||
--secondary: #10B981;
|
||||
--secondary-light: #D1FAE5;
|
||||
--text-dark: #0F172A;
|
||||
--text-muted: #64748B;
|
||||
--border-color: #E2E8F0;
|
||||
--bg-light: #F8FAFC;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Outfit', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
color: var(--text-dark);
|
||||
background-color: #FFFFFF;
|
||||
line-height: 1.6;
|
||||
letter-spacing: -0.02em;
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Header Styling */
|
||||
header {
|
||||
border-bottom: 2px solid var(--text-dark);
|
||||
padding-bottom: 1.5rem;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.doc-category {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 900;
|
||||
color: var(--text-dark);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.meta-info {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.meta-info span strong {
|
||||
color: var(--text-dark);
|
||||
}
|
||||
|
||||
/* Section Styling */
|
||||
section {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 800;
|
||||
color: var(--text-dark);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding-bottom: 0.5rem;
|
||||
margin-bottom: 1.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
h2::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 18px;
|
||||
background-color: var(--primary);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1rem;
|
||||
color: #334155;
|
||||
margin-bottom: 1rem;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/* List & Card Styling */
|
||||
ul {
|
||||
list-style-position: inside;
|
||||
margin-left: 0.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.5rem;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.spec-card {
|
||||
background-color: var(--bg-light);
|
||||
border-left: 4px solid var(--primary);
|
||||
border-radius: 4px;
|
||||
padding: 1.25rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.spec-card h3 {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text-dark);
|
||||
}
|
||||
|
||||
/* Table Styling */
|
||||
.table-container {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
margin: 1.5rem 0;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.9rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: var(--bg-light);
|
||||
font-weight: 700;
|
||||
color: var(--text-dark);
|
||||
padding: 0.75rem 1rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0.75rem 1rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.badge-primary {
|
||||
color: var(--primary);
|
||||
background-color: var(--primary-light);
|
||||
}
|
||||
|
||||
.badge-secondary {
|
||||
color: var(--secondary);
|
||||
background-color: var(--secondary-light);
|
||||
}
|
||||
|
||||
/* Highlight box */
|
||||
.note-box {
|
||||
background-color: #FFFBEB;
|
||||
border: 1px solid #FCD34D;
|
||||
border-radius: 6px;
|
||||
padding: 1rem;
|
||||
margin: 1.5rem 0;
|
||||
font-size: 0.95rem;
|
||||
color: #92400E;
|
||||
}
|
||||
|
||||
.note-box strong {
|
||||
color: #78350F;
|
||||
}
|
||||
|
||||
footer {
|
||||
border-top: 1px solid var(--border-color);
|
||||
padding-top: 1.5rem;
|
||||
margin-top: 4rem;
|
||||
text-align: center;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="doc-category">기획 명세서 / Product Specification</div>
|
||||
<h1>PC 사양 대시보드 시각화 개선 기획서</h1>
|
||||
<div class="meta-info">
|
||||
<span>기획부서: <strong>IT자산관리 태스크포스(TF)</strong></span>
|
||||
<span>최종 수정일: <strong>2026. 05. 28</strong></span>
|
||||
<span>문서 버전: <strong>v1.1 (실제 엑셀 데이터 반영)</strong></span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 1. 개요 및 목적 -->
|
||||
<section>
|
||||
<h2>기획 개요 및 목적</h2>
|
||||
<p>본 기획은 법인별/직무별 PC 자산 사양 현황의 시각적 피로도를 낮추고 데이터 전달력을 고도화하기 위한 개선 작업을 목적으로 합니다. 기존 대시보드 레이아웃의 비정형 비율을 재정립하고, 평균 점수와 권장 점수의 비교 방식을 '다중 막대' 형태에서 <strong>'혼합형(막대 + 꺾은선) 차트'</strong>로 변경하여 대조 직관성을 극대화합니다.</p>
|
||||
</section>
|
||||
|
||||
<!-- 2. 주요 개선 사항 -->
|
||||
<section>
|
||||
<h2>주요 개선 내역</h2>
|
||||
|
||||
<div class="spec-card">
|
||||
<h3>① 가족사별 PC 사양 현황 레이아웃 고도화</h3>
|
||||
<ul>
|
||||
<li><strong>가로 비율 정밀 제어 (1:2)</strong>: 평균 점수 리스트와 막대그래프의 가로 폭 비율을 <code>1 : 2</code>로 엄격하게 고정하여 반응형 레이아웃 환경에서도 깨짐 없는 균형미를 제공합니다.</li>
|
||||
<li><strong>가독성 개선</strong>: 가족사 텍스트 크기를 <code>0.95rem</code>, 평균 사양 점수 텍스트 크기를 <code>1.05rem</code>으로 키우고 세로 행간 여백을 확보해 가시성을 향상시켰습니다.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="spec-card">
|
||||
<h3>② 직무별 PC 사양 평균 및 권장 점수 혼합 시각화</h3>
|
||||
<ul>
|
||||
<li><strong>혼합형 차트(Mixed Chart) 구성</strong>: 직무별 PC 사양 평균 점수는 <span class="badge badge-primary">막대(Bar)</span> 그래프로, 권장 PC 사양 점수는 그 위를 관통하는 <span class="badge badge-secondary">선(Line)</span> 그래프로 표현합니다.</li>
|
||||
<li><strong>레이어 정렬 우선순위 적용</strong>: 차트 정의 시 권장 점수선(Line)이 평균 점수막대(Bar) 뒤에 가리지 않고 항상 맨 앞에 위치하도록 렌더링 우선순위(<code>order</code> 속성)를 명확히 지정합니다.</li>
|
||||
<li><strong>정렬 원복</strong>: 수동 정렬을 지양하고, 직무별 실제 평균 PC 사양 점수가 높은 순으로 자동 내림차순 정렬되도록 하여 가장 자연스러운 시각화를 구축합니다.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. 데이터 정의 -->
|
||||
<section>
|
||||
<h2>직무별 평균 및 권장 사양 점수 스펙</h2>
|
||||
<p>실제 PC 자산 데이터(CPU 및 RAM 점수 연산 결과)와 관리자의 권장 기준선이 아래 명시된 대소 조건 관계를 완벽히 만족하도록 더미 데이터 및 초기 권장 스펙 기준을 재정의했습니다.</p>
|
||||
|
||||
<div class="note-box">
|
||||
<strong>대소 관계 정렬 순서 (실제 평균 점수 기준):</strong><br>
|
||||
AI 개발자 ➔ 편집 디자이너 ➔ 3D 디자이너 ➔ UXUI 디자이너 ➔ 3D 개발자 ➔ 프로그램 개발자 ➔ BIM모델러 ➔ 엔지니어 ➔ 웹 개발자 ➔ 기획자 순서로 실제 평균 점수 순위가 자동 정렬되어 시각화됩니다. (감리원은 실제 자산 데이터 부재로 비교군에서 제외)
|
||||
</div>
|
||||
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>정렬 순위</th>
|
||||
<th>직무명</th>
|
||||
<th>실제 평균 사양 점수 (Bar)</th>
|
||||
<th>기본 권장 사양 점수 (기준)</th>
|
||||
<th>대소 관계 평가</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td><strong>AI 개발자</strong></td>
|
||||
<td>88.0 점</td>
|
||||
<td>95 점</td>
|
||||
<td><span class="badge badge-secondary">미달 (교체 요망)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td><strong>편집 디자이너</strong></td>
|
||||
<td>80.2 점</td>
|
||||
<td>75 점</td>
|
||||
<td><span class="badge badge-secondary">권장 스펙 충족</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td><strong>3D 디자이너</strong></td>
|
||||
<td>78.4 점</td>
|
||||
<td>90 점</td>
|
||||
<td><span class="badge badge-secondary">미달 (교체 요망)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td><strong>UXUI 디자이너</strong></td>
|
||||
<td>72.7 점</td>
|
||||
<td>70 점</td>
|
||||
<td><span class="badge badge-secondary">권장 스펙 충족</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td><strong>3D 개발자</strong></td>
|
||||
<td>67.8 점</td>
|
||||
<td>90 점</td>
|
||||
<td><span class="badge badge-secondary">미달 (교체 요망)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td><strong>프로그램 개발자</strong></td>
|
||||
<td>67.3 점</td>
|
||||
<td>80 점</td>
|
||||
<td><span class="badge badge-secondary">미달 (교체 요망)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7</td>
|
||||
<td><strong>BIM모델러</strong></td>
|
||||
<td>62.1 점</td>
|
||||
<td>75 점</td>
|
||||
<td><span class="badge badge-secondary">미달 (교체 요망)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>8</td>
|
||||
<td><strong>엔지니어</strong></td>
|
||||
<td>42.9 점</td>
|
||||
<td>60 점</td>
|
||||
<td><span class="badge badge-secondary">미달 (교체 요망)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9</td>
|
||||
<td><strong>웹 개발자</strong></td>
|
||||
<td>39.2 점</td>
|
||||
<td>75 점</td>
|
||||
<td><span class="badge badge-secondary">미달 (교체 요망)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>10</td>
|
||||
<td><strong>기획자</strong></td>
|
||||
<td>38.6 점</td>
|
||||
<td>50 점</td>
|
||||
<td><span class="badge badge-secondary">미달 (교체 요망)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>11</td>
|
||||
<td><strong>감리원</strong></td>
|
||||
<td>-</td>
|
||||
<td>40.0 점</td>
|
||||
<td><span class="badge badge-secondary">데이터 없음</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. 기술 구현 세부사항 -->
|
||||
<section>
|
||||
<h2>기술 구현 세부 사양</h2>
|
||||
<div class="spec-card" style="border-left-color: var(--secondary);">
|
||||
<h3>차트 렌더링 옵션 (Chart.js v4.x+)</h3>
|
||||
<p>평균 PC 사양 점수를 보여주는 데이터셋과 권장 PC 사양 점수를 보여주는 데이터셋을 하나의 Canvas 엘리먼트에 그리되, 레이어 겹침과 시인성을 확보하기 위해 다음 세부 옵션을 바인딩합니다.</p>
|
||||
<ul>
|
||||
<li><strong>Average Dataset</strong>: <code>type: 'bar', order: 2, backgroundColor: '#6366F1'</code></li>
|
||||
<li><strong>Recommended Dataset</strong>: <code>type: 'line', order: 1, borderColor: '#10B981', borderWidth: 3, pointRadius: 4, fill: false</code></li>
|
||||
<li><strong>정렬 로직</strong>: <code>Object.keys(jobScores).sort((a, b) => jobScores[b].avg - jobScores[a].avg)</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>© 2026 HM ITAM Systems. All rights reserved.</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
60
docs/plans/PLAN_ASSET_HISTORY.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# 자산 이력 누적 관리 시스템 (Cumulative Asset History System) 구현 계획
|
||||
|
||||
본 문서는 자산의 라이프사이클(조직, 사용자, 용도, 상태 변동)을 체계적으로 추적하고 누적 관리하기 위한 기술적 설계 및 단계별 구현 계획을 담고 있습니다.
|
||||
|
||||
## 1. 목적
|
||||
- 자산 정보 수정 시 중요 변경 사항을 자동으로 감지하여 이력(Log)화
|
||||
- 과거부터 현재까지의 변동 사항을 타임라인 형태로 시각화하여 자산 흐름 파악
|
||||
- 데이터 정합성을 위해 서버 측에서 변경 전/후 스냅샷 비교 방식 채택
|
||||
|
||||
## 2. 관리 대상 이력 (Watch Fields)
|
||||
다음 항목의 변경이 발생할 경우 이력을 자동 생성합니다.
|
||||
1. **조직 변동**: `current_dept` (현 사용조직) ↔ `previous_dept` 업데이트 포함
|
||||
2. **사용자 변동**: `user_current` (현 사용자) ↔ `previous_user` 업데이트 포함
|
||||
3. **용도 변경**: `asset_type`, `current_role` (예: 개인PC -> 공용PC)
|
||||
4. **상태 변경**: `hw_status` (예: 운영 -> 수리, 재고 -> 폐기 등)
|
||||
|
||||
## 3. 기술 설계 (Technical Design)
|
||||
|
||||
### A. 데이터베이스 (DB)
|
||||
- **대상 테이블**: `asset_history`
|
||||
- **컬럼 구조 활용 및 보완**:
|
||||
- `asset_id`: 대상 자산 식별자
|
||||
- `event_type`: 변경 유형 (DEPT_CHANGE, USER_CHANGE, ROLE_CHANGE, STATUS_CHANGE)
|
||||
- `details`: "상태 변경: 운영 -> 수리" 와 같이 읽기 쉬운 문자열 저장
|
||||
- `cost`: 관련 비용 발생 시 기록 (수리비 등)
|
||||
- `log_user`: 변경을 수행한 작업자
|
||||
- `log_date`: 변경 발생 일시
|
||||
|
||||
### B. 백엔드 (Server-side Logic)
|
||||
- **위치**: `server.js` 의 `POST /api/asset/:category/save` 엔드포인트
|
||||
- **동작 흐름**:
|
||||
1. **Snapshot**: 인서트/업데이트 수행 전, 기존 DB의 데이터를 `SELECT`하여 메모리에 저장.
|
||||
2. **Comparison**: 요청된 신규 데이터와 기존 데이터를 필드별로 대조.
|
||||
3. **Auto-logging**: 변경점이 발견되면 `asset_history` 테이블에 즉시 인서트.
|
||||
4. **Transaction**: 모든 로그 생성이 자산 저장과 하나의 트랜잭션으로 묶여야 함.
|
||||
|
||||
### C. 프론트엔드 (UI/UX)
|
||||
- **위치**: `HWModal.ts` 우측 `modal-history-area`
|
||||
- **개선 사항**:
|
||||
- `renderHistory()` 함수를 고도화하여 이벤트 타입별 아이콘/컬러 적용.
|
||||
- "이전 값 ➔ 이후 값" 형태의 직관적인 레이아웃 도입.
|
||||
- 스크롤을 통한 무제한 누적 이력 조회 지원.
|
||||
|
||||
## 4. 단계별 구현 로직
|
||||
|
||||
### 1단계: 서버 로직 고도화
|
||||
- `server.js`에 비교 함수(`compareAndLog`) 구현.
|
||||
- 각 자산 카테고리별 저장 로직에 비교 로직 삽입.
|
||||
|
||||
### 2단계: DB 데이터 마이그레이션 (필요시)
|
||||
- 기존 자산의 `current_dept` 등을 `previous_dept`로 밀어내는 로직 점검.
|
||||
|
||||
### 3단계: UI 타임라인 렌더링 개선
|
||||
- `modal.css`에 이력 전용 스타일(이벤트 뱃지 등) 추가.
|
||||
- `HWModal.ts`에서 최신 로그를 실시간으로 다시 불러오는 로직 확인.
|
||||
|
||||
## 5. 검증 계획
|
||||
- **자동 감지 테스트**: 상태 변경 후 저장 시 우측 이력에 즉시 한 줄이 추가되는지 확인.
|
||||
- **다중 변경 테스트**: 조직과 사용자를 동시에 변경했을 때 두 개의 로그가 생성되는지 확인.
|
||||
- **데이터 무결성**: 수정을 취소하거나 저장 실패 시 로그가 남지 않는지(Transaction) 확인.
|
||||
48
docs/plans/design_rule.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# 🎨 ITAM 시스템 디자인 가이드 (Design Guide)
|
||||
|
||||
본 문서는 ITAM(IT Asset Management System)의 시각적 일관성과 사용자 경험을 유지하기 위한 핵심 디자인 원칙을 정의합니다.
|
||||
|
||||
---
|
||||
|
||||
### 1. 디자인 철학 (Design Philosophy)
|
||||
* **Minimalist & Stark**: Vercel 스타일의 극도로 간결하고 현대적인 디자인을 지향합니다.
|
||||
* **Achromatic Base**: 블랙(#171717)과 화이트를 기본으로 하며, 정보의 구분은 얇은 헤어라인(#ebebeb)을 사용합니다.
|
||||
* **Fluid & Responsive**: 고정된 픽셀 대신 화면 크기에 비례하여 UI 밀도가 변하는 유동적 스케일링 시스템을 적용합니다.
|
||||
|
||||
### 2. 타이포그래피 및 자간 (Typography & Letter-spacing)
|
||||
* **Font Family**: `Pretendard` 단일 폰트를 사용합니다.
|
||||
* **Letter-spacing**: 모든 텍스트에 `-0.02em` (-2%) 자간을 적용하여 밀도 있는 가독성을 확보합니다.
|
||||
* **Typography Scale**:
|
||||
* **XS**: `clamp(10px, 1.2vmin + 0.2vw, 15px)` - 보조 텍스트
|
||||
* **SM**: `clamp(12px, 1.4vmin + 0.3vw, 18px)` - 필터, 일반 라벨, 테이블 헤더
|
||||
* **Base**: `clamp(14px, 1.6vmin + 0.4vw, 22px)` - 본문, 테이블 데이터
|
||||
* **MD**: `clamp(18px, 2.5vmin + 0.5vw, 30px)` - 섹션 소제목
|
||||
* **LG**: `clamp(24px, 4vmin + 0.6vw, 48px)` - 페이지 대제목
|
||||
* **XL**: `clamp(32px, 6vmin + 0.8vw, 72px)` - 핵심 통계 지표
|
||||
* **Layout Units**:
|
||||
* **Header Height**: `clamp(50px, 8vmin, 90px)`
|
||||
* **Base Spacing**: `clamp(0.75rem, 3vmin, 3rem)`
|
||||
* **Radius**: `clamp(6px, 1.5vmin, 16px)`
|
||||
|
||||
### 3. 컬러 팔레트 (Vercel Stark Palette)
|
||||
* **Primary**: `#171717` (Stark Black) - 텍스트, 주요 버튼, 강조 요소.
|
||||
* **Secondary**: `#888888` (Mute) - 보조 텍스트, 비활성 아이콘.
|
||||
* **Border**: `#ebebeb` (Hairline) - 정보 구분선.
|
||||
* **Background**: `#ffffff` (Canvas), `#fafafa` (Soft), `#f5f5f5` (Soft 2).
|
||||
* **Accents**: Blue(`#0070f3`), Orange(`#f5a623`), Danger(`#ee0000`).
|
||||
|
||||
### 4. 컴포넌트 및 레이아웃 규칙 (Component Rules)
|
||||
* **Header & Navigation**:
|
||||
* 상단 1열 통합 바 형태를 유지하며, GNB와 LNB를 동일 라인에 배치하여 공간을 효율적으로 사용합니다.
|
||||
* **Unified Filter Bar**:
|
||||
* 검색창과 필터는 상단 타이틀 바로 아래(기존 액션 버튼 라인)까지 올려서 배치합니다.
|
||||
* **Action Group**: '자산 추가', '부품 마스터' 등의 주요 액션 버튼은 검색창과 같은 라인의 최우측에 정렬합니다.
|
||||
* **Dashboard**:
|
||||
* **Single-Screen View**: 1920*1080(또는 1920*919) 해상도에서 스크롤 없이 한 화면에 핵심 정보가 모두 보이도록 최적화합니다.
|
||||
* **Fixed Charts**: 차트 내부 숫자나 요소에 애니메이션(`animation: false`) 및 플로팅 레이블을 배제하여 정적인 안정성을 확보합니다.
|
||||
* **Footer**:
|
||||
* 화면 최하단에 위치하며, 텍스트는 **우측 정렬(Right-aligned)**합니다.
|
||||
* 상단에 1px 헤어라인 구분선을 가집니다.
|
||||
* **Security & UX**:
|
||||
* **Text Selection**: 사용자의 실수에 의한 UI 드래그 방지를 위해 입력창(`input`, `textarea`)을 제외한 전체 영역의 텍스트 선택을 차단합니다.
|
||||
* **View Toggle**: '서버' 탭 등 특정 탭에서만 '목록보기' 체크박스를 통해 뷰를 전환하며, 그 외 화면은 리스트 중심의 UI를 제공합니다.
|
||||
646
index.html
@@ -1,614 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>ITAM 자산관리 ERP</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable.min.css" />
|
||||
<link rel="stylesheet" href="/src/styles/common.css" />
|
||||
<link rel="stylesheet" href="/src/styles/modal.css" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-layout">
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<h1>HM <span>ITAM</span></h1>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>한맥가족 자산관리시스템</title>
|
||||
<link rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable.min.css" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="app-layout" id="app-layout" style="display: none;">
|
||||
<!-- Single-Line Integrated Header -->
|
||||
<header class="main-header">
|
||||
<div class="header-container" id="nav-container">
|
||||
<div class="brand">
|
||||
<img src="/image 92.png" alt="Logo" class="main-logo" />
|
||||
<h1>한맥자산관리시스템</h1>
|
||||
</div>
|
||||
|
||||
<div class="nav-section">
|
||||
<h3><i data-lucide="cpu"></i> 하드웨어</h3>
|
||||
<ul id="nav-hw" class="nav-list">
|
||||
<li class="active" data-category="hw" data-tab="대시보드"><i data-lucide="layout-dashboard"></i> 대시보드</li>
|
||||
<li data-category="hw" data-tab="개인PC"><i data-lucide="monitor"></i> 개인PC</li>
|
||||
<li data-category="hw" data-tab="서버"><i data-lucide="server"></i> 서버</li>
|
||||
<li data-category="hw" data-tab="스토리지"><i data-lucide="database"></i> 스토리지</li>
|
||||
<li data-category="hw" data-tab="전산비품"><i data-lucide="laptop"></i> 전산비품</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Navigation (GNB + LNB in same row) -->
|
||||
<nav class="integrated-nav" id="main-nav">
|
||||
<!-- JS will render main items and sub items here side-by-side -->
|
||||
</nav>
|
||||
|
||||
<div class="nav-section">
|
||||
<h3><i data-lucide="layers"></i> 소프트웨어</h3>
|
||||
<ul id="nav-sw" class="nav-list">
|
||||
<li data-category="sw" data-tab="대시보드"><i data-lucide="layout-dashboard"></i> 대시보드</li>
|
||||
<li data-category="sw" data-tab="구독SW"><i data-lucide="calendar-clock"></i> 구독 소프트웨어</li>
|
||||
<li data-category="sw" data-tab="영구SW"><i data-lucide="key"></i> 영구 소프트웨어</li>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<div class="main-wrapper">
|
||||
<header class="top-header">
|
||||
<div class="header-title">
|
||||
<h2 id="current-tab-title">하드웨어 / 대시보드</h2>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<!-- 엑셀 컨트롤러 묶음 -->
|
||||
<button id="btn-download-template" class="btn btn-outline" title="초기 데이터 입력을 위한 전체 엑셀 템플릿 다운로드">
|
||||
<i data-lucide="download"></i> 통합 양식 다운로드
|
||||
</button>
|
||||
<label for="excel-upload" class="btn btn-outline" title="작성된 엑셀 파일 일괄 업로드">
|
||||
<i data-lucide="upload"></i> 엑셀 업로드
|
||||
<div class="header-actions">
|
||||
<div class="role-switcher" id="role-switcher">
|
||||
<span class="role-label user active">실무자</span>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="role-toggle-checkbox">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
<input type="file" id="excel-upload" accept=".xlsx, .xls" style="display: none;" />
|
||||
<button id="btn-export-excel" class="btn btn-primary" title="마스터 데이터 전체를 엑셀로 저장">
|
||||
<i data-lucide="file-spreadsheet"></i> 일괄 엑셀 저장
|
||||
</button>
|
||||
<button id="btn-add-asset" class="btn btn-primary hidden">
|
||||
<i data-lucide="plus"></i> 자산 추가
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="content-area" id="main-content">
|
||||
<!-- 대시보드 뷰, 또는 데이터 테이블 뷰가 JavaScript로 주입됩니다 -->
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- HW Asset Modal -->
|
||||
<div id="hw-asset-modal" class="modal-overlay hidden">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 id="hw-modal-title">자산 상세 정보</h2>
|
||||
<button id="btn-close-hw-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="hw-asset-form" class="grid-form">
|
||||
<input type="hidden" id="hw-asset-id" />
|
||||
<input type="hidden" id="hw-asset-type" /> <!-- 개인PC, 서버 등 저장용 -->
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-법인">법인</label>
|
||||
<input type="text" id="hw-법인" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="hw-비품유형-group" style="display:none;">
|
||||
<label for="hw-비품유형">비품유형</label>
|
||||
<select id="hw-비품유형" class="form-control" style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px;">
|
||||
<option value="노트북">노트북</option>
|
||||
<option value="태블릿">태블릿</option>
|
||||
<option value="휴대폰">휴대폰</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-자산코드">자산코드</label>
|
||||
<input type="text" id="hw-자산코드" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-명칭">명칭</label>
|
||||
<input type="text" id="hw-명칭" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-위치">위치</label>
|
||||
<input type="text" id="hw-위치" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-관리자">관리자</label>
|
||||
<input type="text" id="hw-관리자" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-IP주소">IP주소</label>
|
||||
<input type="text" id="hw-IP주소" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-MACaddress">MAC address</label>
|
||||
<input type="text" id="hw-MACaddress" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-OS">OS</label>
|
||||
<input type="text" id="hw-OS" />
|
||||
</div>
|
||||
|
||||
<div class="form-group full-width">
|
||||
<label for="hw-HW사양">H/W 사양</label>
|
||||
<textarea id="hw-HW사양" rows="2"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-구매일">구매일</label>
|
||||
<input type="text" id="hw-구매일" placeholder="ex) 2024-01-01" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-금액">금액</label>
|
||||
<input type="text" id="hw-금액" placeholder="ex) 1,000,000" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hw-납품업체">납품업체</label>
|
||||
<input type="text" id="hw-납품업체" />
|
||||
</div>
|
||||
|
||||
<div class="form-group full-width">
|
||||
<label style="font-size:0.875rem;">품의서 (파일)</label>
|
||||
<div style="display:flex; align-items:center; gap:0.5rem;">
|
||||
<input type="file" id="hw-품의서" style="font-size:0.875rem;" />
|
||||
<span id="hw-품의서명" style="font-size:0.75rem; color:var(--text-light)"></span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btn-delete-hw-asset" class="btn btn-outline btn-danger">삭제</button>
|
||||
<div class="footer-actions">
|
||||
<button id="btn-cancel-hw-modal" class="btn btn-outline">취소</button>
|
||||
<button id="btn-save-hw-asset" class="btn btn-primary">저장</button>
|
||||
<span class="role-label admin">관리자</span>
|
||||
</div>
|
||||
<button id="btn-admin-page" class="hidden"></button> <!-- JS 호환용 숨김 -->
|
||||
<button id="btn-open-guide-header" class="btn btn-outline" title="프로세스 가이드">
|
||||
<i data-lucide="book-open"></i> 가이드
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- PC Asset Modal -->
|
||||
<div id="pc-asset-modal" class="modal-overlay hidden">
|
||||
<div class="modal-content wide">
|
||||
<div class="modal-header">
|
||||
<h2 id="pc-modal-title">개인PC 상세 정보</h2>
|
||||
<button id="btn-close-pc-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-body-split">
|
||||
<div class="modal-form-area">
|
||||
<form id="pc-asset-form" class="grid-form">
|
||||
<input type="hidden" id="pc-asset-id" />
|
||||
<input type="hidden" id="pc-asset-type" value="개인PC" />
|
||||
<!-- Main Content Area -->
|
||||
<main class="content-area" id="main-content">
|
||||
<!-- Components inject views here -->
|
||||
</main>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-법인">법인</label>
|
||||
<select id="pc-법인" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
|
||||
<option value="한맥">한맥 (HM)</option>
|
||||
<option value="삼안">삼안 (SM)</option>
|
||||
<option value="바론">바론 (BR)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-자산코드">자산코드</label>
|
||||
<input type="text" id="pc-자산코드" placeholder="ex) HM-PC-2018-001" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-사용자">사용자</label>
|
||||
<input type="text" id="pc-사용자" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-위치">위치</label>
|
||||
<input type="text" id="pc-위치" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-CPU">CPU</label>
|
||||
<input type="text" id="pc-CPU" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-GPU">GPU</label>
|
||||
<input type="text" id="pc-GPU" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-RAM">RAM</label>
|
||||
<input type="text" id="pc-RAM" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-SSD1">SSD1</label>
|
||||
<input type="text" id="pc-SSD1" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-SSD2">SSD2</label>
|
||||
<input type="text" id="pc-SSD2" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-HDD1">HDD1</label>
|
||||
<input type="text" id="pc-HDD1" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-HDD2">HDD2</label>
|
||||
<input type="text" id="pc-HDD2" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-구매일">구매일</label>
|
||||
<input type="text" id="pc-구매일" placeholder="ex) 2024-01-01" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-금액">금액</label>
|
||||
<input type="text" id="pc-금액" placeholder="ex) 1,000,000" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\B(?=(\d{3})+(?!\d))/g, ',')" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pc-납품업체">납품업체</label>
|
||||
<input type="text" id="pc-납품업체" />
|
||||
</div>
|
||||
|
||||
<div class="form-group full-width">
|
||||
<label style="font-size:0.875rem;">품의서 (파일)</label>
|
||||
<div style="display:flex; align-items:center; gap:0.5rem;">
|
||||
<input type="file" id="pc-품의서" style="font-size:0.875rem;" />
|
||||
<span id="pc-품의서명" style="font-size:0.75rem; color:var(--text-light)"></span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-history-area">
|
||||
<div class="history-header">
|
||||
<h3><i data-lucide="history" style="width:16px; height:16px;"></i> 수정 이력</h3>
|
||||
</div>
|
||||
<div id="pc-history-list" class="history-timeline">
|
||||
<div class="empty-history">이력이 없습니다.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btn-delete-pc-asset" class="btn btn-outline btn-danger">삭제</button>
|
||||
<div class="footer-actions">
|
||||
<button id="btn-cancel-pc-modal" class="btn btn-outline">취소</button>
|
||||
<button id="btn-save-pc-asset" class="btn btn-primary">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<p>© 2026 BARON Consultant Co,Ltd. All rights reserved.</p>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Storage Asset Modal -->
|
||||
<div id="storage-asset-modal" class="modal-overlay hidden">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 id="storage-modal-title">스토리지 상세 정보</h2>
|
||||
<button id="btn-close-storage-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="storage-asset-form" class="grid-form">
|
||||
<input type="hidden" id="storage-asset-id" />
|
||||
<input type="hidden" id="storage-asset-type" value="스토리지" />
|
||||
<!-- All modals are injected dynamically -->
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-법인">법인</label>
|
||||
<select id="storage-법인" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
|
||||
<option value="한맥">한맥 (HM)</option>
|
||||
<option value="삼안">삼안 (SM)</option>
|
||||
<option value="바론">바론 (BR)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-유형">유형</label>
|
||||
<select id="storage-유형" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
|
||||
<option value="NAS">NAS</option>
|
||||
<option value="DAS">DAS</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-자산코드">자산코드</label>
|
||||
<input type="text" id="storage-자산코드" placeholder="ex) HM-NAS-2024-001" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-명칭">명칭</label>
|
||||
<input type="text" id="storage-명칭" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-위치">위치</label>
|
||||
<input type="text" id="storage-위치" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-모델명">모델명</label>
|
||||
<input type="text" id="storage-모델명" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-용량">용량</label>
|
||||
<input type="text" id="storage-용량" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-담당자_정">담당자(정)</label>
|
||||
<input type="text" id="storage-담당자_정" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-담당자_부">담당자(부)</label>
|
||||
<input type="text" id="storage-담당자_부" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-IP주소">IP주소</label>
|
||||
<input type="text" id="storage-IP주소" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-MAC주소">MAC 주소</label>
|
||||
<input type="text" id="storage-MAC주소" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-구매일">구매일</label>
|
||||
<input type="text" id="storage-구매일" placeholder="ex) 2024-01-01" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-금액">금액</label>
|
||||
<input type="text" id="storage-금액" placeholder="ex) 1,000,000" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="storage-납품업체">납품업체</label>
|
||||
<input type="text" id="storage-납품업체" />
|
||||
</div>
|
||||
|
||||
<div class="form-group full-width">
|
||||
<label style="font-size:0.875rem;">품의서 (파일)</label>
|
||||
<div style="display:flex; align-items:center; gap:0.5rem;">
|
||||
<input type="file" id="storage-품의서" style="font-size:0.875rem;" />
|
||||
<span id="storage-품의서명" style="font-size:0.75rem; color:var(--text-light)"></span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btn-delete-storage-asset" class="btn btn-outline btn-danger">삭제</button>
|
||||
<div class="footer-actions">
|
||||
<button id="btn-cancel-storage-modal" class="btn btn-outline">취소</button>
|
||||
<button id="btn-save-storage-asset" class="btn btn-primary">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SW Asset Modal -->
|
||||
<div id="sw-asset-modal" class="modal-overlay hidden">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 id="sw-modal-title">S/W 상세 정보</h2>
|
||||
<button id="btn-close-sw-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="sw-asset-form" class="grid-form">
|
||||
<input type="hidden" id="sw-asset-id" />
|
||||
<input type="hidden" id="sw-asset-type" />
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-분야">분야</label>
|
||||
<select id="sw-분야" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
|
||||
<option value="업무공통">업무공통</option>
|
||||
<option value="개발S/W">개발S/W</option>
|
||||
<option value="디자인">디자인</option>
|
||||
<option value="설계S/W">설계S/W</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-법인">법인</label>
|
||||
<select id="sw-법인" required style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;">
|
||||
<option value="한맥">한맥 (HM)</option>
|
||||
<option value="삼안">삼안 (SM)</option>
|
||||
<option value="바론">바론 (BR)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-부서">부서</label>
|
||||
<input type="text" id="sw-부서" placeholder="ex) 경영지원팀" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-제품명">제품명</label>
|
||||
<input type="text" id="sw-제품명" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-구매일">구매일</label>
|
||||
<input type="text" id="sw-구매일" placeholder="ex) 2024-01-01" />
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="sw-구독일-group">
|
||||
<label for="sw-구독일">구독일(시작~끝)</label>
|
||||
<input type="text" id="sw-구독일" placeholder="ex) 2024-01-01 ~ 2024-12-31" />
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="sw-유지보수-group" style="display:none;">
|
||||
<label for="sw-유지보수여부">유지보수 여부</label>
|
||||
<label style="display:flex; align-items:center; gap:0.5rem; height: 38px;">
|
||||
<input type="checkbox" id="sw-유지보수여부" /> 대상 여부
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-금액">금액</label>
|
||||
<input type="text" id="sw-금액" placeholder="ex) 1,000,000" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-수량">수량 (보유량)</label>
|
||||
<input type="number" id="sw-수량" min="1" value="1" style="width: 100%; padding: 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.875rem;" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-계정명">계정명</label>
|
||||
<input type="text" id="sw-계정명" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-납품업체">납품업체</label>
|
||||
<input type="text" id="sw-납품업체" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-비고">비고</label>
|
||||
<input type="text" id="sw-비고" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btn-delete-sw-asset" class="btn btn-outline btn-danger">삭제</button>
|
||||
<div class="footer-actions">
|
||||
<button id="btn-cancel-sw-modal" class="btn btn-outline">취소</button>
|
||||
<button id="btn-save-sw-asset" class="btn btn-primary">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SW User Management Modal -->
|
||||
<div id="sw-user-modal" class="modal-overlay hidden">
|
||||
<div class="modal-content" style="max-width: 600px;">
|
||||
<div class="modal-header">
|
||||
<h2 id="sw-user-modal-title">S/W 할당 사용자 목록</h2>
|
||||
<button id="btn-close-sw-user-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="sw-user-asset-id" />
|
||||
|
||||
<div style="text-align: right; margin-bottom: 0.5rem;">
|
||||
<button type="button" id="btn-open-add-user" class="btn btn-primary" style="padding: 0.25rem 1rem;"><i data-lucide="plus"></i> 새 사용자 추가</button>
|
||||
</div>
|
||||
|
||||
<div class="table-container" style="max-height: 250px; overflow-y: auto; border: 1px solid #e2e8f0; border-radius: 4px; margin-top:0;">
|
||||
<table style="width:100%; border-collapse: collapse; font-size:0.875rem;">
|
||||
<thead style="position: sticky; top: 0; background: var(--bg-light); z-index: 10;">
|
||||
<tr style="border-bottom: 1px solid var(--border);">
|
||||
<th style="padding:0.5rem; text-align:left;">법인</th>
|
||||
<th style="padding:0.5rem; text-align:left;">부서/팀</th>
|
||||
<th style="padding:0.5rem; text-align:left;">직위</th>
|
||||
<th style="padding:0.5rem; text-align:left;">이름</th>
|
||||
<th style="padding:0.5rem; text-align:center;">사용기간</th>
|
||||
<th style="padding:0.5rem; text-align:center;">첨부파일</th>
|
||||
<th style="padding:0.5rem; text-align:center;">관리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="user-list-body">
|
||||
<!-- Users will be injected here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer" style="justify-content: flex-end;">
|
||||
<div class="footer-actions">
|
||||
<button id="btn-cancel-sw-user-modal" class="btn btn-outline">닫기</button>
|
||||
<button id="btn-save-sw-user-mapping" class="btn btn-primary">변경사항 저장</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SW User Form Modal (Add / Edit) -->
|
||||
<div id="sw-user-edit-modal" class="modal-overlay hidden" style="z-index: 1100;">
|
||||
<div class="modal-content" style="max-width: 500px;">
|
||||
<div class="modal-header">
|
||||
<h2 id="sw-user-edit-modal-title">사용자 추가</h2>
|
||||
<button id="btn-close-sw-user-edit-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="edit-user-idx" value="-1" />
|
||||
<div style="display:grid; grid-template-columns: 1fr 1fr; gap:0.5rem;">
|
||||
<div class="form-group">
|
||||
<label for="new-user-법인" style="font-size:0.875rem;">법인</label>
|
||||
<select id="new-user-법인" class="form-control" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;">
|
||||
<option value="한맥">한맥</option><option value="삼안">삼안</option><option value="바론">바론</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new-user-부서" style="font-size:0.875rem;">부서</label>
|
||||
<input type="text" id="new-user-부서" placeholder="ex: 기술부" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new-user-팀" style="font-size:0.875rem;">팀</label>
|
||||
<input type="text" id="new-user-팀" placeholder="ex: 개발1팀" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new-user-직위" style="font-size:0.875rem;">직위</label>
|
||||
<input type="text" id="new-user-직위" placeholder="ex: 대리" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" />
|
||||
</div>
|
||||
<div class="form-group" style="grid-column: span 2;">
|
||||
<label for="new-user-이름" style="font-size:0.875rem;">이름 <span style="color:var(--danger)">*</span></label>
|
||||
<input type="text" id="new-user-이름" placeholder="ex: 홍길동" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" required />
|
||||
</div>
|
||||
<div class="form-group" style="grid-column: span 2;">
|
||||
<label for="new-user-사용기간" style="font-size:0.875rem;">사용기간</label>
|
||||
<input type="text" id="new-user-사용기간" placeholder="ex: 2024.01~12" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" />
|
||||
</div>
|
||||
<div class="form-group" style="grid-column: span 2;">
|
||||
<label style="font-size:0.875rem;">신청서 (파일)</label>
|
||||
<div style="display:flex; align-items:center; gap:0.5rem;">
|
||||
<input type="file" id="new-user-신청서" style="font-size:0.875rem;" />
|
||||
<span id="new-user-신청서명" style="font-size:0.75rem; color:var(--text-light)"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer" style="justify-content: flex-end;">
|
||||
<div class="footer-actions">
|
||||
<button id="btn-cancel-sw-user-edit" class="btn btn-outline">취소</button>
|
||||
<button id="btn-save-edit-user" class="btn btn-primary">확인</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Detail Modal -->
|
||||
<div id="dashboard-detail-modal" class="modal-overlay hidden" style="z-index: 1200;">
|
||||
<div class="modal-content" style="max-width: 1000px; max-height: 80vh; display: flex; flex-direction: column;">
|
||||
<div class="modal-header">
|
||||
<h2 id="dashboard-detail-modal-title">상세 자산 목록</h2>
|
||||
<button id="btn-close-dashboard-detail" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body" style="overflow-y: auto; flex: 1; padding: 0;">
|
||||
<div class="table-container" style="box-shadow: none; border-radius: 0;">
|
||||
<table style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th><th>유형</th><th>자산코드</th><th>명칭/모델</th>
|
||||
<th>위치</th><th>담당/사용자</th><th>구매일</th><th>금액</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dashboard-detail-tbody">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
label/DevExpress.Data.v14.1.dll
Normal file
BIN
label/DevExpress.Printing.v14.1.Core.dll
Normal file
BIN
label/DevExpress.Utils.v14.1.dll
Normal file
BIN
label/DevExpress.XtraEditors.v14.1.dll
Normal file
BIN
label/DevExpress.XtraGrid.v14.1.dll
Normal file
BIN
label/DevExpress.XtraLayout.v14.1.dll
Normal file
BIN
label/DevExpress.XtraPrinting.v14.1.dll
Normal file
BIN
label/LabelPrinter.exe
Normal file
BIN
label/Newtonsoft.Json.dll
Normal file
BIN
label/WebQuery.dll
Normal file
4
label/config.ini
Normal file
@@ -0,0 +1,4 @@
|
||||
[PRINT]
|
||||
FONT=8
|
||||
LEFT=143
|
||||
TOP=40
|
||||