fix: 빌드 에러 및 포트 동기화 수정

This commit is contained in:
2026-04-21 11:40:54 +09:00
parent 153e422180
commit 34baea9143
7 changed files with 106 additions and 31 deletions

View File

@@ -1,26 +1,26 @@
/**
* 모든 모달의 공통 기능 (닫기, ESC 처리, 배경 클릭 등)을 관리하는 베이스 모듈입니다.
*/
export function initBaseModal() {
const closeAllModals = () => {
const modals = document.querySelectorAll('.modal-overlay');
modals.forEach(modal => modal.classList.add('hidden'));
};
export function closeModals() {
const modals = document.querySelectorAll('.modal-overlay');
modals.forEach(modal => modal.classList.add('hidden'));
}
export function initBaseModal() {
// ESC 키로 닫기
window.addEventListener('keydown', (e) => {
if (e.key === 'Escape') closeAllModals();
if (e.key === 'Escape') closeModals();
});
// 배경(Overlay) 클릭 시 닫기 (동적 생성된 모달 대응을 위해 이벤트 위임 고려 가능하나 일단 단순 구현)
// 배경(Overlay) 클릭 시 닫기
document.addEventListener('click', (e) => {
const target = e.target as HTMLElement;
if (target.classList.contains('modal-overlay')) {
closeAllModals();
closeModals();
}
});
return { closeAllModals };
return { closeAllModals: closeModals };
}
/**

View File

@@ -98,7 +98,7 @@ export function openSwUsageDetail(title: string, list: SoftwareAsset[]) {
thead.innerHTML = `<tr><th>No</th><th>법인</th><th>제품명</th><th>수량</th><th>사용중</th><th>사용가능</th></tr>`;
tbody.innerHTML = '';
list.forEach((sw, idx) => {
const assigned = state.masterData.swUsers.filter(u => u.swId === sw.id).length;
const assigned = state.masterData.swUsers.filter(u => u.sw_id === sw.id).length;
const tr = document.createElement('tr');
tr.innerHTML = `<td>${idx+1}</td><td>${sw.}</td><td>${sw.}</td><td>${sw.}</td><td>${assigned}</td><td>${Number(sw.) - assigned}</td>`;
tbody.appendChild(tr);

View File

@@ -6,7 +6,7 @@ import { CORP_LIST, ORG_LIST } from './SharedData';
import { generateOptionsHTML, setFieldValue, getFieldValue } from './ModalUtils';
let currentSwUserAsset: SoftwareAsset | null = null;
let tempSwUsers: SWUser[] = [];
let tempSwUsers: any[] = [];
const SW_USER_MODAL_HTML = `
<div id="sw-user-modal" class="modal-overlay hidden">
@@ -105,7 +105,9 @@ export function openSwUserModal(asset: SoftwareAsset) {
// 기존 사용자 데이터 복사 (원본 보호를 위해 temp 사용)
const existingMapping = state.masterData.swUsers.find(u => u.sw_id === asset.id);
tempSwUsers = existingMapping ? JSON.parse(JSON.stringify(existingMapping.userDataList || [])) : [];
tempSwUsers = existingMapping ? (existingMapping.userData || []).map((u: any) => ({
법인: u[0], 부서: u[1], 직위: u[2], 이름: u[3], 사용기간: u[4], 신청서명: u[5]
})) : [];
renderUserList();
modal.classList.remove('hidden');
@@ -124,7 +126,7 @@ function renderUserList() {
tempSwUsers.forEach((user, idx) => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${user. || user. || ''}</td>
<td>${user. || ''}</td>
<td>${user. || ''}</td>
<td>${user. || ''}</td>
<td>${user. || ''}</td>
@@ -169,7 +171,7 @@ function openUserEditSubModal(idx: number = -1) {
if (idx > -1) {
const user = tempSwUsers[idx];
setFieldValue('new-user-법인', user. || user.);
setFieldValue('new-user-법인', user.);
setFieldValue('new-user-부서', user.);
setFieldValue('new-user-직위', user.);
setFieldValue('new-user-이름', user.);
@@ -203,7 +205,7 @@ export function initSwUserModal(onSave: () => void, closeModals: () => void) {
const existingIdx = state.masterData.swUsers.findIndex(u => u.sw_id === currentSwUserAsset!.id);
const newMapping = {
sw_id: currentSwUserAsset!.id,
userDataList: tempSwUsers
userData: tempSwUsers.map(u => [u., u., u., u., u., u.])
};
if (existingIdx > -1) state.masterData.swUsers[existingIdx] = newMapping as any;
@@ -233,7 +235,7 @@ function saveUserDataToList() {
const = Input.files && Input.files.length > 0 ? Input.files[0].name : (idx > -1 ? tempSwUsers[idx]. : '');
const userData: any = {
구매법인: getFieldValue('new-user-법인'),
법인: getFieldValue('new-user-법인'),
부서: getFieldValue('new-user-부서'),
직위: getFieldValue('new-user-직위'),
이름: getFieldValue('new-user-이름'),

View File

@@ -196,5 +196,5 @@ export function generateDummyData(): MasterAssetData {
});
}
return { pc, server, storage, equip, mobile, subSw, permSw, swUsers, logs };
return { pc, server, storage, equip, mobile, subSw, permSw, cloud: [], swUsers, logs, sw: [], hw: [] };
}

View File

@@ -40,6 +40,7 @@ export interface HardwareAsset {
비고?: string;
현사용조직?: string;
이전사용조직?: string;
detail_purpose?: string;
}
export interface SoftwareAsset {
@@ -60,6 +61,7 @@ export interface SoftwareAsset {
계정명: string;
납품업체: string;
비고: string;
자산번호?: string;
플랫폼명?: string;
결제수단?: string;
결제일?: string;
@@ -96,8 +98,11 @@ export interface MasterAssetData {
mobile: HardwareAsset[];
subSw: SoftwareAsset[];
permSw: SoftwareAsset[];
swUsers: any[]; // { sw_id, userData: [] } 형태로 처리
cloud: SoftwareAsset[];
swUsers: SWUser[];
logs: HardwareLog[];
sw: SoftwareAsset[];
hw: HardwareAsset[];
}
const HW_TABS = ['개인PC', '서버', '스토리지', '전산비품', '모바일기기'];
@@ -164,7 +169,7 @@ export async function parseExcel(file: File): Promise<MasterAssetData> {
reader.onload = (e) => {
try {
const workbook = XLSX.read(e.target?.result, { type: 'binary' });
const data: MasterAssetData = { pc: [], server: [], storage: [], equip: [], mobile: [], subSw: [], permSw: [], swUsers: [], logs: [] };
const data: MasterAssetData = { pc: [], server: [], storage: [], equip: [], mobile: [], subSw: [], permSw: [], cloud: [], swUsers: [], logs: [], sw: [], hw: [] };
workbook.SheetNames.forEach(sheetName => {
const rows = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]) as any[];
if (sheetName === '개인PC') {

View File

@@ -15,12 +15,14 @@ export interface MasterAssetData {
// 동료 코드 호환용 통합 배열 (프론트엔드 로직용)
sw: SoftwareAsset[];
hw: HardwareAsset[];
}
export interface AppState {
activeCategory: 'dashboard' | 'hw' | 'sw';
activeSubTab: string; // '대시보드', '개인PC', '서버', '스토리지', '전산비품', '구독SW', '영구SW', '클라우드'
activeCategory: 'dashboard' | 'hw' | 'sw' | 'ops';
activeSubTab: string;
masterData: MasterAssetData;
activeCharts: any[];
}
// 초기 상태
@@ -38,8 +40,10 @@ export const state: AppState = {
cloud: [],
sw: [], // 호환용
swUsers: [],
logs: []
}
logs: [],
hw: []
},
activeCharts: []
};
/**
@@ -83,12 +87,19 @@ export async function loadMasterDataFromDB() {
}
}
// 동료 코드 호환을 위한 통합 sw 배열 생성
// 동료 코드 호환을 위한 통합 sw/hw 배열 생성
state.masterData.sw = [
...state.masterData.subSw,
...state.masterData.permSw,
...state.masterData.cloud
];
state.masterData.hw = [
...state.masterData.pc,
...state.masterData.server,
...state.masterData.storage,
...state.masterData.equip,
...state.masterData.mobile
];
console.log('✅ 모든 DB 데이터 로드 및 통합 완료');
return true;