feat/refactor: 자산관리 시스템 기능 고도화 및 UI/UX 개선

1. 컬럼 드래그 너비 조정 버그 수정 및 개선 (ListFactory.ts)
   - 드래그 완료 시 click 이벤트 전파 차단으로 정렬(sorting) 오작동 방지
   - getBoundingClientRect().width 활용한 소수점 정밀 너비 고정 및 레이아웃 시프트 방지
   - 마우스 업 시점의 모든 컬럼 너비를 config.columns에 동기화하여 재렌더링 시 너비 영속성 보장

2. PC 자산 모달 필드 잠금 정책 세분화 (HWModal.ts)
   - 자산 추가(add) 모드에서는 모든 필드(사용자 정보 포함) 입력 허용
   - 자산 수정(edit) 모드에서만 사용자/조직 정보 관련 필드(lockedUserFields) 선택적 잠금 적용
   - 시스템 사양, 네트워크, 위치, 구매 등 다른 모든 섹션은 수정 가능하도록 복구 및 안내 배너 갱신

3. 관리자 전용 메뉴 단일 페이지 앱(SPA) 통합 (Navigation.ts, main.ts, MapEditor.ts)
   - 기존의 실사 승인 탭과 독립 실행형 좌표 에디터(MapEditor)를 GNB '관리도구' 하위 메뉴로 통합
   - '실사 승인', '위치지정'을 GNB에서 ↳ 화살표 및 11px 폰트의 계층형 탭 스타일로 렌더링
   - 내부 서브 탭 바를 삭제하고 메인 영역 전체 높이(calc(100vh - var(--header-height) - 48px))를 확보
   - 다른 탭으로 이동 시 MapEditor 인스턴스의 window 이벤트 및 전역 바인딩을 소거하는 destroy() 리사이클 구현

4. 자산 이력(History) 가독성 개선 및 포맷팅 (HWModal.ts, SWModal.ts, DomainModal.ts)
   - 자산 변경 이력 로그를 일자별로 그룹화하여 타임라인 렌더링
   - 최초 등록 데이터에 녹색 '[최초등록]' 배지 추가
   - 기존의 생 JSON 이력 데이터를 친절한 한국어 텍스트 포맷으로 가공하여 가독성 극대화
This commit is contained in:
이태훈
2026-06-26 17:31:39 +09:00
parent 87459c8f44
commit 8129f85071
7 changed files with 397 additions and 65 deletions

View File

@@ -6,6 +6,7 @@ import { renderDashboard } from './views/DashboardView';
import { renderSWTable } from './views/SW_Table';
import { renderLocationView } from './views/LocationView';
import { renderAuditApprovalView } from './views/AuditApprovalView';
import { MapEditor } from './views/MapEditor';
import { initBaseModal } from './components/Modal/BaseModal';
import { initHwModal, openHwModal } from './components/Modal/HWModal';
import { initSwModal, openSwModal } from './components/Modal/SWModal';
@@ -21,11 +22,19 @@ import { pcFlowModal } from './components/Modal/PCFlowModal';
import { createIcons, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, History, RefreshCcw, BookOpen, Settings } from 'lucide';
let activeMapEditorInstance: MapEditor | null = null;
// 화면 갱신 통합 핸들러
function refreshView(tab?: string) {
async function refreshView(tab?: string) {
const mainContent = document.getElementById('main-content')!;
if (!mainContent) return;
// Clean up any active MapEditor instance when navigating away
if (activeMapEditorInstance) {
activeMapEditorInstance.destroy();
activeMapEditorInstance = null;
}
const activeTab = tab || state.activeSubTab;
if (activeTab === '대시보드') {
@@ -34,7 +43,48 @@ function refreshView(tab?: string) {
}
if (activeTab === '실사 승인') {
renderAuditApprovalView(mainContent);
await renderAuditApprovalView(mainContent);
return;
}
if (activeTab === '위치지정') {
// Render Map Editor directly into main content to maximize working area
mainContent.innerHTML = `
<div class="map-editor-page-wrapper" style="display: flex; flex: 1; height: calc(100vh - var(--header-height) - 48px); overflow: hidden; width: 100%;">
<!-- Left: File Selector -->
<div class="file-sidebar" id="file-sidebar"></div>
<!-- Center: Main Editor -->
<div class="editor-container" id="container">
<div class="img-wrapper" id="wrapper">
<img src="" id="target-img" alt="Map Image">
</div>
</div>
<!-- Right: Control Panel -->
<div class="sidebar">
<h2>Map Editor <small class="editor-version">v3.0</small></h2>
<div class="current-path" id="current-path">파일을 선택하세요</div>
<p>
드래그하여 구역을 정의하세요. 저장 버튼을 누르면 즉시 시스템에 반영됩니다.
</p>
<div class="box-list" id="box-list"></div>
<div class="actions" style="display: flex; flex-direction: column; gap: 0.5rem;">
<button id="btn-clear-all" class="btn btn-outline">전체 삭제</button>
<button id="btn-print-map-qrs" class="btn btn-outline btn-primary">이 도면 QR 일괄인쇄</button>
<button id="btn-save-server" class="btn btn-primary">서버에 즉시 저장</button>
<div id="save-status"></div>
</div>
</div>
</div>
`;
// Initialize MapEditor instance
const editor = new MapEditor();
await editor.init();
activeMapEditorInstance = editor;
return;
}