초기 PM 소스 전체 업로드

This commit is contained in:
koj729
2026-06-12 17:14:03 +09:00
commit 4e33c9a02a
1769 changed files with 377797 additions and 0 deletions

View File

@@ -0,0 +1,586 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>UI/UX Screen Specification</title>
<!-- Google Fonts - Inter & 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=Inter:wght@300;400;500;600;700&family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
<style>
:root {
--primary: #1e5149;
--primary-dark: #142e29;
--primary-soft: #e9eeed;
--border: #d2dcdb;
--accent: #4db251;
--bg: #f4f7f6;
--card-bg: #ffffff;
--text-main: #1f2937;
--text-muted: #4b5563;
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
--sidebar-width: 280px;
/* UI Status Colors */
--color-active: #4db251;
--bg-active: #eef8ee;
--color-inactive: #a5b9b6;
--bg-inactive: #f1f5f9;
--color-danger: #ef4444;
--bg-danger: #fee2e2;
--color-warning: #ff9800;
--bg-warning: #fff5e6;
}
* {
box-sizing: border-box;
}
body {
font-family: 'Inter', 'Noto Sans KR', sans-serif;
background-color: var(--bg);
color: var(--text-main);
line-height: 1.7;
margin: 0;
padding: 0;
display: flex;
}
/* Sidebar Navigation */
aside {
width: var(--sidebar-width);
background: linear-gradient(180deg, var(--primary-dark) 0%, #0c1a18 100%);
color: #ffffff;
height: 100vh;
position: fixed;
top: 0;
left: 0;
overflow-y: auto;
border-right: 1px solid rgba(255, 255, 255, 0.1);
padding: 24px;
z-index: 100;
}
aside h2 {
font-size: 1.15rem;
font-weight: 700;
margin-bottom: 24px;
color: var(--accent);
display: flex;
align-items: center;
gap: 8px;
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
padding-bottom: 12px;
}
aside ul {
list-style: none;
padding: 0;
margin: 0;
}
aside li {
margin-bottom: 8px;
}
aside a {
color: #b3c5c2;
text-decoration: none;
font-size: 0.9rem;
display: block;
padding: 8px 12px;
border-radius: 6px;
transition: all 0.2s ease;
}
aside a:hover, aside li.active a {
color: #ffffff;
background-color: rgba(255, 255, 255, 0.08);
padding-left: 16px;
}
aside .category-title {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: #628781;
margin: 16px 0 8px 12px;
font-weight: 700;
}
/* Main Content */
main {
margin-left: var(--sidebar-width);
flex-grow: 1;
padding: 40px 50px;
max-width: 1000px;
}
header {
border-bottom: 2px solid var(--border);
padding-bottom: 24px;
margin-bottom: 40px;
}
header h1 {
font-size: 2.2rem;
font-weight: 700;
margin: 0 0 10px 0;
color: var(--primary);
}
header .subtitle {
font-size: 1.1rem;
color: var(--text-muted);
margin: 0;
}
/* Content Sections */
section {
background-color: var(--card-bg);
border-radius: 12px;
padding: 30px;
margin-bottom: 30px;
box-shadow: var(--shadow);
border: 1px solid var(--border);
}
h2.section-title {
font-size: 1.4rem;
font-weight: 700;
color: var(--primary);
margin-top: 0;
margin-bottom: 20px;
border-left: 4px solid var(--accent);
padding-left: 12px;
}
h3 {
font-size: 1.2rem;
font-weight: 600;
color: var(--primary-dark);
margin-top: 24px;
margin-bottom: 12px;
border-bottom: 1px solid #f1f5f9;
padding-bottom: 8px;
}
h4 {
font-size: 1.05rem;
font-weight: 600;
color: var(--primary);
margin-top: 16px;
margin-bottom: 8px;
}
p {
margin: 0 0 16px 0;
color: var(--text-main);
}
/* Color Chips */
.color-palette {
display: flex;
flex-wrap: wrap;
gap: 16px;
margin: 20px 0;
}
.color-chip {
flex: 1 1 200px;
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
background-color: #ffffff;
box-shadow: var(--shadow);
}
.color-box {
height: 60px;
width: 100%;
}
.color-details {
padding: 10px 12px;
}
.color-name {
font-weight: 700;
font-size: 0.85rem;
margin-bottom: 2px;
}
.color-value {
font-family: monospace;
font-size: 0.8rem;
color: var(--text-muted);
}
/* Layout Preview map */
.layout-preview {
background-color: #1e293b;
color: #cbd5e1;
padding: 20px;
border-radius: 8px;
font-family: monospace;
font-size: 0.8rem;
white-space: pre;
overflow-x: auto;
margin: 20px 0;
line-height: 1.4;
}
/* Status Badge */
.status-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.8rem;
font-weight: 600;
}
.status-badge-active { background-color: var(--bg-active); color: var(--color-active); }
.status-badge-inactive { background-color: var(--bg-inactive); color: var(--color-inactive); }
.status-badge-danger { background-color: var(--bg-danger); color: var(--color-danger); }
.status-badge-warning { background-color: var(--bg-warning); color: var(--color-warning); }
/* Tables */
table {
width: 100%;
border-collapse: collapse;
margin: 16px 0;
font-size: 0.88rem;
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--border);
}
th {
background-color: var(--primary-soft);
color: var(--primary-dark);
font-weight: 600;
text-align: left;
padding: 10px 14px;
border-bottom: 2px solid var(--border);
}
td {
padding: 10px 14px;
border-bottom: 1px solid var(--border);
color: var(--text-main);
}
tr:last-child td {
border-bottom: none;
}
/* Lists */
ul {
padding-left: 20px;
margin-bottom: 16px;
}
li {
margin-bottom: 6px;
}
.spec-card {
border: 1px solid var(--border);
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
background-color: #f9fafb;
}
</style>
</head>
<body>
<!-- Sidebar Navigation -->
<aside>
<h2>📁 PM_ver4 Spec</h2>
<ul>
<li><a href="#overview">설계서 소개</a></li>
</ul>
<div class="category-title">01. 디자인 시스템</div>
<ul>
<li><a href="#design-system">디자인 가이드라인</a></li>
</ul>
<div class="category-title">02. 공통 프레임</div>
<ul>
<li><a href="#layout">App Frame 레이아웃</a></li>
</ul>
<div class="category-title">03. 화면별 UI/UX 명세</div>
<ul>
<li><a href="#screen-dashboard">📊 종합 용량 및 접속자</a></li>
<li><a href="#screen-project">🏗️ 프로젝트 관리</a></li>
<li><a href="#screen-banner">📢 실시간 배너 공지</a></li>
<li><a href="#screen-user">👥 사용자 관리</a></li>
<li><a href="#screen-audit">🔎 감사 로그 조회</a></li>
<li><a href="#screen-policy">⚙️ 보관 및 삭제 설정</a></li>
<li><a href="#screen-codes">🔑 공통 코드 관리</a></li>
</ul>
</aside>
<!-- Main Content -->
<main>
<header id="overview">
<h1>UI/UX Screen Specification</h1>
<p class="subtitle">대시보드 및 관리자 화면 기능 명세서 (UI/UX Specification)</p>
</header>
<!-- Section 1 -->
<section id="design-system">
<h2 class="section-title">1. 공통 UI 가이드라인 및 디자인 시스템</h2>
<p>관리자 패널의 모든 화면 레이아웃, 컴포넌트 명세, 사용자 액션 및 데이터 정합성 검증 규칙은 본 시스템의 디자인 규칙을 준수합니다.</p>
<h3>① 색상 토큰 (Color Tokens)</h3>
<div class="color-palette">
<div class="color-chip">
<div class="color-box" style="background-color: #1e5149;"></div>
<div class="color-details">
<div class="color-name">Primary Forest Green</div>
<div class="color-value">#1e5149</div>
</div>
</div>
<div class="color-chip">
<div class="color-box" style="background-color: #142e29;"></div>
<div class="color-details">
<div class="color-name">Dark Teal Sidebar</div>
<div class="color-value">#142e29</div>
</div>
</div>
<div class="color-chip">
<div class="color-box" style="background-color: #d2dcdb;"></div>
<div class="color-details">
<div class="color-name">Light Green Gray Border</div>
<div class="color-value">#d2dcdb</div>
</div>
</div>
<div class="color-chip">
<div class="color-box" style="background-color: #e9eeed;"></div>
<div class="color-details">
<div class="color-name">Soft Accent Green BG</div>
<div class="color-value">#e9eeed</div>
</div>
</div>
</div>
<h3>② 서체 (Typography)</h3>
<ul>
<li><strong>서체 패밀리</strong>: <code>'Pretendard Variable', 'Pretendard', 'Inter', 'Noto Sans KR', sans-serif</code></li>
<li><strong>글꼴 크기 명세</strong>:
<ul>
<li>페이지 메인 타이틀: <code>1.25rem</code> (700 Bold)</li>
<li>카드 타이틀: <code>1.05rem</code> (700 Bold)</li>
<li>일반 본문 및 테이블 데이터: <code>0.875rem</code> (500 Medium / 600 Semi-Bold)</li>
<li>Muted 보조 텍스트: <code>0.8rem</code> / <code>0.75rem</code></li>
</ul>
</li>
</ul>
<h3>③ 공통 그리드 & 테이블 (Table Grid Rules)</h3>
<ul>
<li><strong>순번 표시 (NO)</strong>: 모든 테이블 그리드의 1열은 데이터 인덱스 번호(<code>NO</code>)를 필수 노출합니다.</li>
<li><strong>가로 구분선</strong>: 답답한 디자인을 방지하기 위해 세로 테두리(Vertical Borders)는 일절 노출하지 않으며, 가로 행 구분선만 노출합니다.</li>
<li><strong>행 선택 인터랙션</strong>: 마우스 호버 시 <code>var(--primary-soft)</code> 배경색을 지정하며, 클릭 행 활성화 시 텍스트 두께 변경으로 인한 줄높이 왜곡이 없도록 패딩 상속(inherit) 속성을 적용하여 균일한 행 높이를 유지합니다.</li>
</ul>
<h3>④ 공통 모달 팝업 (Modal Overlay Rules)</h3>
<ul>
<li><strong>백드롭</strong>: <code>rgba(20, 30, 29, 0.6)</code> 반투명 딤 및 <code>backdrop-filter: blur(4px)</code> 효과로 모달 포커스를 고정합니다.</li>
<li><strong>트랜지션</strong>: <code>fade-in</code><code>slide-up (translateY 30px to 0)</code>이 일괄 적용되어 매끄러운 팝업 동작을 보장합니다.</li>
</ul>
</section>
<!-- Section 2 -->
<section id="layout">
<h2 class="section-title">2. 레이아웃 구조 설계 (App Frame Layout)</h2>
<p>LNB, 상단 헤더, 그리고 메인 콘텐츠 탭 영역의 수평/수직 분할 아키텍처는 다음과 같습니다.</p>
<div class="layout-preview">
+-------------------------------------------------------------------------+
| LNB (좌측 사이드바) | Main Header (상단 헤더) |
| 📁 PM_ver4 Admin | [Header Title] [Admin Profile] |
|-------------------------+-----------------------------------------------|
| - Dashboards | Main Content (메인 콘텐츠 탭 영역) |
| 📊 종합 용량/접속자 | |
| - 프로젝트 관리 | +-----------------------------------------+ |
| 🏗️ 프로젝트 관리 | | 카드 1 (필터 / 테이블 리스트) | |
| 📢 실시간 배너 공지 | +-----------------------------------------+ |
| - 사용자 및 권한 | | 카드 2 (상세정보 뷰 / 팝업 연동 리스트) | |
| 👥 사용자 관리 | +-----------------------------------------+ |
| - 시스템 감사 및 환경 | |
| 🔎 감사 로그 조회 | |
| ⚙️ 자동 삭제 설정 | |
| 🔑 공통 코드 관리 | |
+-------------------------------------------------------------------------+</div>
</section>
<!-- Section 3 -->
<section id="screen-dashboard">
<h2 class="section-title">3. 화면별 상세 UI 및 기능 설계</h2>
<h3>📊 화면 1: 종합 용량 및 접속자 현황 (Dashboard)</h3>
<p>상단 3열 KPI 요약 카드와 하단 스토리지 프로그레스바 및 실시간 소켓 접속자 테이블 구조입니다.</p>
<div class="spec-card">
<h4>① 주요 UI 컴포넌트</h4>
<ul>
<li><strong>스토리지 KPI 카드</strong>: 전체 현장의 총 한도 용량 대비 누적 사용 용량 실시간 합산 표시 (예: <code>💾 9.70 GB / 20 GB</code>).</li>
<li><strong>접속자 KPI 카드</strong>: 현재 소켓 서버 연결 세션 수 노출.</li>
<li><strong>압축작업 KPI 카드</strong>: Redis(BullMQ) 내 대기중인 압축 건수.</li>
<li><strong>현장별 스토리지 사용 현황</strong>: 각 프로젝트 ID/명칭, 게이지바 및 사용량 정보(GB / 백분율% / 파일수량개) 동시 렌더링.</li>
</ul>
<h4>② 실시간 접속 현황 테이블 사양</h4>
<table>
<thead>
<tr>
<th style="width: 10%;">NO</th>
<th style="width: 25%;">사용자 ID</th>
<th style="width: 25%;">접속 IP</th>
<th style="width: 25%;">현재 조회 경로</th>
<th style="width: 15%;">작업</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>admin_test</td>
<td>127.0.0.1</td>
<td><code>/PM_TEST_01/archive</code></td>
<td><span class="status-badge status-badge-danger" style="cursor: pointer;">강제퇴장</span></td>
</tr>
</tbody>
</table>
</div>
</section>
<section id="screen-project">
<h3>🏗️ 화면 2: 프로젝트 관리 (Project Management)</h3>
<p>좌측 프로젝트 목록 그리드와 우측 프로젝트별 참여자 및 배정 통제 그리드 구조입니다.</p>
<div class="spec-card">
<h4>① 프로젝트 목록 테이블 사양 (좌측 카드)</h4>
<p>출력 컬럼: <code>NO</code> | <code>프로젝트 ID</code> | <code>현장명</code> | <code>카테고리</code> | <code>용량 제한(GB)</code> | <code>상태</code> | <code>관리(수정/삭제)</code></p>
<ul>
<li>행 클릭 시, 우측의 '참여 권한 사용자 목록'이 해당 프로젝트 정보로 자동 리바인딩됩니다.</li>
<li><strong>삭제 제한</strong>: 관련 테이블(tb_data, tb_official_doc_file, tb_banner_notice 등)에 현장 ID 사용 이력이 있으면 삭제 불가능하며 경고 메시지가 발생합니다.</li>
<li><strong>신규 프로젝트 등록 및 수정 모달 (projectModalOverlay)</strong>: 프로젝트 ID(수정 시 Readonly), 프로젝트명, 단축명, 카테고리 Select, 스토리지 제한(GB), 상태를 편집합니다.</li>
</ul>
<h4>② 참여 권한 사용자 목록 (우측 카드 - 병합 영역)</h4>
<p>출력 컬럼: <code>NO</code> | <code>사용자 ID</code> | <code>이름</code> | <code>부서/직급</code> | <code>권한 등급</code> | <code>작업(배정제외)</code></p>
<ul>
<li><strong>권한 등급 변경</strong>: 인라인 셀렉터(Admin, Sub-Master, Worker, Viewer)로 권한 레벨 즉시 업데이트.</li>
<li><strong>사용자 배정 추가 팝업 모달 (assignModalOverlay)</strong>: 현재 현장에 미배정된 사용자들을 체크박스로 다중 선택하여 일괄 추가합니다. 또한 목록 선택식을 지원하기 위해 우측 하단 배정 대기 목록에서도 '즉시 배정' 단축 버튼을 제공합니다.</li>
</ul>
</div>
</section>
<section id="screen-banner">
<h3>📢 화면 3: 실시간 배너 공지 (Banner Notice)</h3>
<p>상단 배너 등록 폼 카드 및 하단 이력 검색 조건 필터와 이력 목록 그리드 구조입니다.</p>
<div class="spec-card">
<h4>① 배너 공지 등록 폼</h4>
<ul>
<li>입력 필드: 대상 프로젝트 선택(특정 현장 또는 전체 현장 'all' 매핑), 등록일(임의 편집 지원), 시작일, 종료일, 공지 자막 텍스트.</li>
<li>송출 등록 제출 시, 오늘 일자와 비교하여 즉시 이력에 추가되고 상태 배지가 실시간 부여됩니다.</li>
</ul>
<h4>② 이력 목록 필터 및 이력 테이블</h4>
<ul>
<li><strong>검색 필터</strong>: 송출 상태(전체, 송출중, 예약됨, 만료) 및 등록일(from ~ to) 날짜 범위 지정 검색.</li>
<li><strong>테이블 명세</strong>: <code>NO</code> | <code>등록일</code> | <code>대상 프로젝트</code> | <code>공지 내용</code> | <code>시작일</code> | <code>종료일</code> | <code>송출 상태</code> | <code>작업</code></li>
<li><strong>송출 중지 통제</strong>: 아직 기간이 유효한 행(송출중, 예약됨)에만 <code>[송출 중지]</code> 버튼이 노출 및 활성화되며, 이미 만료된 이력은 <code>[중지 완료]</code> 비활성 텍스트로 대체하여 이중 제어를 차단합니다.</li>
</ul>
</div>
</section>
<section id="screen-user">
<h3>👥 화면 4: 사용자 관리 (User Management)</h3>
<p>좌측 사용자 마스터 리스트 및 우측 선택된 사용자의 참여 권한 프로젝트 리스트업 구조입니다.</p>
<div class="spec-card">
<h4>① 사용자 계정 목록 (좌측 카드)</h4>
<p>출력 컬럼: <code>NO</code> | <code>아이디</code> | <code>이름</code> | <code>소속/직급</code> | <code>그룹</code> | <code>상태</code> | <code>관리(수정/삭제)</code></p>
<ul>
<li>행 클릭 시, 해당 사용자가 참여하고 있는 프로젝트 리스트가 우측 카드에 즉시 바인딩됩니다.</li>
<li><strong>삭제 제한</strong>: 권한 테이블(tb_permission)에 현장 배정/참여 권한 정보가 등록되어 있으면 삭제가 불가능하며 경고 메시지가 발생합니다.</li>
<li><strong>사용자 등록 및 수정 모달 (userModalOverlay)</strong>: 아이디(수정 시 Readonly), 패스워드, 이름, 회사명, 부서, 직급, 권한 그룹 지정 select, 재직 상태(재직/퇴직잠금) 지정.</li>
</ul>
<h4>② 권한부여 프로젝트 목록 (우측 카드)</h4>
<p>출력 컬럼: <code>NO</code> | <code>프로젝트 ID</code> | <code>프로젝트명</code> | <code>부여 권한 등급</code></p>
</div>
</section>
<section id="screen-audit">
<h3>🔎 화면 5: 감사 로그 조회 (Audit Logs)</h3>
<p>파일 조작 중요 이벤트(삭제, 이동, 다운로드) 목록 및 검색 조회 화면입니다.</p>
<div class="spec-card">
<h4>① 감사 로그 목록 사양</h4>
<p>출력 컬럼: <code>NO</code> | <code>일시</code> | <code>프로젝트</code> | <code>사용자 ID</code> | <code>접속 IP</code> | <code>조작 액션</code> | <code>조작 대상 경로(코드박스 스타일)</code></p>
<ul>
<li>필터링 항목: 사용자 ID 검색 입력란, 조작 액션 Dropdown, 검색 기능.</li>
</ul>
</div>
</section>
<section id="screen-policy">
<h3>⚙️ 화면 6: 자동 보관 및 파일 삭제 정책 설정 (Delete Policy)</h3>
<p>시스템 글로벌 일괄 정책 설정 영역, 실시간 예정 시나리오 요약, 그리고 배치 처리 이력 구조입니다.</p>
<div class="spec-card">
<h4>① 시스템 공통 자동 삭제 정책 설정 폼 [글로벌 정책 공통화]</h4>
<ul>
<li><strong>입력 필드</strong>: 정책 활성화 여부(Toggle/Select), 최소 유지 파일 개수 기준(숫자 입력), 자동 삭제 제한 기한(일) (숫자 입력).</li>
<li><strong>글로벌 통합</strong>: 기존의 프로젝트 개별 Dropdown은 완전히 배제하고, 전체 현장에 동일하게 일괄 반영합니다.</li>
</ul>
<h4>② 보존 정책 실시간 요약 (Dynamic Summary)</h4>
<ul>
<li>폼의 입력값을 변경하는 즉시 요약 영역 텍스트가 시나리오 문구로 동적 조합되어 나타납니다.</li>
<li>예: <code>"현재 전체 공통 설정에 따라, 각 현장의 보관 파일 수가 100개 미만이고 30일이 지나면 자동 삭제 배치 스케줄러가 작동합니다."</code></li>
</ul>
<h4>③ 자동 삭제 처리 이력 테이블 사양</h4>
<p>출력 컬럼: <code>NO</code> | <code>자동 처리 일자</code> | <code>프로젝트 ID</code> | <code>삭제 처리 폴더 경로</code> | <code>적용 기준</code> | <code>처리 결과(성공 배지)</code></p>
<ul>
<li>정책 값 저장 완료 시 이력 로그의 대상 프로젝트 ID 자리에는 <code>'SYSTEM'</code>이 기입됩니다.</li>
</ul>
</div>
</section>
<section id="screen-codes">
<h3>🔑 화면 7: 공통 코드 관리 (Common Code Management)</h3>
<p>대분류 마스터 및 세부 코드 리스트가 배치되는 상하 2단 수직 정렬 레이아웃 구조입니다.</p>
<div class="spec-card">
<h4>① 대분류 코드 마스터 (상단 카드)</h4>
<p>출력 컬럼: <code>NO</code> | <code>대분류 코드</code> | <code>대분류 코드명</code> | <code>사용</code> | <code>관리(수정/삭제)</code></p>
<ul>
<li>행을 선택(click)하면 해당 행이 하이라이트(selected)되며, 하단의 세부 코드 그리드가 동적으로 새로고침됩니다.</li>
<li><strong>대분류 등록 및 수정 모달 (codeMasterModalOverlay)</strong>: 대분류 코드, 명칭, 사용여부, 비고 설명 입력.</li>
</ul>
<h4>② 세부 소분류 코드 목록 (하단 카드)</h4>
<p>출력 컬럼: <code>NO</code> | <code>소분류 코드</code> | <code>조합 코드 (base_code)</code> | <code>코드 명칭</code> | <code>정렬 순서</code> | <code>사용</code> | <code>관리(수정/삭제)</code></p>
<ul>
<li><strong>유효성 방어 차단</strong>: 상단 대분류 테이블에서 행을 클릭하여 선택하지 않은 상태에서는 하단의 <code>[ 세부코드 등록]</code> 버튼이 강제 비활성화(disabled)되며, 팝업 접근 시 안내 팝업 및 경고 텍스트(<code>"상단에서 대분류 코드를 선택해 주세요."</code>)를 노출합니다.</li>
<li><strong>조합 코드(base_code)</strong>: 소분류 생성 완료 제출 시, <code>대분류코드_소분류코드</code> 형태로 자동 결합되어 저장됩니다.</li>
<li><strong>삭제 제한 (RESTRICT)</strong>: 마스터 대분류 코드를 삭제할 경우, 하위 세부 코드(code_detail)가 존재하면 대분류 삭제가 차단되고 경고 메시지를 노출합니다. (세부 코드가 먼저 삭제되어 비어있을 때만 대분류 삭제 가능)</li>
</ul>
</div>
</section>
</main>
</body>
</html>