- 순찰/점검 기능 개선 (zone-detail 페이지 추가) - 출근/근태 시스템 개선 (연차 조회, 근무현황) - 작업분석 대분류 그룹화 및 마이그레이션 스크립트 - 모바일 네비게이션 UI 추가 - NAS 배포 도구 및 문서 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
268 lines
8.9 KiB
JavaScript
268 lines
8.9 KiB
JavaScript
/**
|
|
* Work Analysis Module Loader
|
|
* 작업 분석 모듈들을 순서대로 로드하고 초기화하는 로더
|
|
*/
|
|
|
|
class WorkAnalysisModuleLoader {
|
|
constructor() {
|
|
this.modules = [
|
|
{ name: 'API Client', path: '/js/work-analysis/api-client.js', loaded: false },
|
|
{ name: 'Data Processor', path: '/js/work-analysis/data-processor.js', loaded: false },
|
|
{ name: 'State Manager', path: '/js/work-analysis/state-manager.js', loaded: false },
|
|
{ name: 'Table Renderer', path: '/js/work-analysis/table-renderer.js', loaded: false },
|
|
{ name: 'Chart Renderer', path: '/js/work-analysis/chart-renderer.js', loaded: false },
|
|
{ name: 'Main Controller', path: '/js/work-analysis/main-controller.js', loaded: false }
|
|
];
|
|
|
|
this.loadingPromise = null;
|
|
}
|
|
|
|
/**
|
|
* 모든 모듈 로드
|
|
* @returns {Promise} 로딩 완료 Promise
|
|
*/
|
|
async loadAll() {
|
|
if (this.loadingPromise) {
|
|
return this.loadingPromise;
|
|
}
|
|
|
|
this.loadingPromise = this._loadModules();
|
|
return this.loadingPromise;
|
|
}
|
|
|
|
/**
|
|
* 모듈들을 순차적으로 로드
|
|
*/
|
|
async _loadModules() {
|
|
console.log('🚀 작업 분석 모듈 로딩 시작');
|
|
|
|
try {
|
|
// 의존성 순서대로 로드
|
|
for (const module of this.modules) {
|
|
await this._loadModule(module);
|
|
}
|
|
|
|
console.log('✅ 모든 작업 분석 모듈 로딩 완료');
|
|
this._onAllModulesLoaded();
|
|
|
|
} catch (error) {
|
|
console.error('❌ 모듈 로딩 실패:', error);
|
|
this._onLoadingError(error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 개별 모듈 로드
|
|
* @param {Object} module - 모듈 정보
|
|
*/
|
|
async _loadModule(module) {
|
|
return new Promise((resolve, reject) => {
|
|
console.log(`📦 로딩 중: ${module.name}`);
|
|
|
|
const script = document.createElement('script');
|
|
script.src = module.path;
|
|
script.type = 'text/javascript';
|
|
|
|
script.onload = () => {
|
|
module.loaded = true;
|
|
console.log(`✅ 로딩 완료: ${module.name}`);
|
|
resolve();
|
|
};
|
|
|
|
script.onerror = (error) => {
|
|
console.error(`❌ 로딩 실패: ${module.name}`, error);
|
|
reject(new Error(`Failed to load ${module.name}: ${module.path}`));
|
|
};
|
|
|
|
document.head.appendChild(script);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 모든 모듈 로딩 완료 시 호출
|
|
*/
|
|
_onAllModulesLoaded() {
|
|
// 전역 변수 확인
|
|
const requiredGlobals = [
|
|
'WorkAnalysisAPI',
|
|
'WorkAnalysisDataProcessor',
|
|
'WorkAnalysisState',
|
|
'WorkAnalysisTableRenderer',
|
|
'WorkAnalysisChartRenderer'
|
|
];
|
|
|
|
const missingGlobals = requiredGlobals.filter(name => !window[name]);
|
|
|
|
if (missingGlobals.length > 0) {
|
|
console.warn('⚠️ 일부 전역 객체가 누락됨:', missingGlobals);
|
|
}
|
|
|
|
// 하위 호환성을 위한 전역 함수들 설정
|
|
this._setupLegacyFunctions();
|
|
|
|
// 모듈 로딩 완료 이벤트 발생
|
|
window.dispatchEvent(new CustomEvent('workAnalysisModulesLoaded', {
|
|
detail: { modules: this.modules }
|
|
}));
|
|
|
|
console.log('🎉 작업 분석 시스템 준비 완료');
|
|
}
|
|
|
|
/**
|
|
* 하위 호환성을 위한 전역 함수 설정
|
|
*/
|
|
_setupLegacyFunctions() {
|
|
// 기존 HTML에서 사용하던 함수들을 새 모듈 시스템으로 연결
|
|
const legacyFunctions = {
|
|
// 기간 확정
|
|
confirmPeriod: () => {
|
|
if (window.WorkAnalysisMainController) {
|
|
window.WorkAnalysisMainController.handlePeriodConfirm();
|
|
}
|
|
},
|
|
|
|
// 분석 모드 변경
|
|
switchAnalysisMode: (mode) => {
|
|
if (window.WorkAnalysisState) {
|
|
window.WorkAnalysisState.setAnalysisMode(mode);
|
|
}
|
|
},
|
|
|
|
// 탭 변경
|
|
switchTab: (tabId) => {
|
|
if (window.WorkAnalysisState) {
|
|
window.WorkAnalysisState.setCurrentTab(tabId);
|
|
}
|
|
},
|
|
|
|
// 개별 분석 함수들
|
|
analyzeWorkStatus: () => {
|
|
if (window.WorkAnalysisMainController) {
|
|
window.WorkAnalysisMainController.analyzeWorkStatus();
|
|
}
|
|
},
|
|
|
|
analyzeProjectDistribution: () => {
|
|
if (window.WorkAnalysisMainController) {
|
|
window.WorkAnalysisMainController.analyzeProjectDistribution();
|
|
}
|
|
},
|
|
|
|
analyzeWorkerPerformance: () => {
|
|
if (window.WorkAnalysisMainController) {
|
|
window.WorkAnalysisMainController.analyzeWorkerPerformance();
|
|
}
|
|
},
|
|
|
|
analyzeErrorAnalysis: () => {
|
|
if (window.WorkAnalysisMainController) {
|
|
window.WorkAnalysisMainController.analyzeErrorAnalysis();
|
|
}
|
|
}
|
|
};
|
|
|
|
// 전역 함수로 등록
|
|
Object.assign(window, legacyFunctions);
|
|
|
|
console.log('🔗 하위 호환성 함수 설정 완료');
|
|
}
|
|
|
|
/**
|
|
* 로딩 에러 처리
|
|
*/
|
|
_onLoadingError(error) {
|
|
// 에러 UI 표시
|
|
const container = document.querySelector('.analysis-container');
|
|
if (container) {
|
|
const errorHTML = `
|
|
<div style="
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 50vh;
|
|
text-align: center;
|
|
color: #ef4444;
|
|
">
|
|
<div style="font-size: 4rem; margin-bottom: 1rem;">⚠️</div>
|
|
<h2 style="margin-bottom: 1rem;">모듈 로딩 실패</h2>
|
|
<p style="margin-bottom: 2rem; color: #666;">
|
|
작업 분석 시스템을 로드하는 중 오류가 발생했습니다.<br>
|
|
페이지를 새로고침하거나 관리자에게 문의하세요.
|
|
</p>
|
|
<button onclick="location.reload()" style="
|
|
padding: 0.75rem 1.5rem;
|
|
background: #3b82f6;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 0.5rem;
|
|
cursor: pointer;
|
|
font-size: 1rem;
|
|
">
|
|
페이지 새로고침
|
|
</button>
|
|
<details style="margin-top: 2rem; text-align: left; max-width: 600px;">
|
|
<summary style="cursor: pointer; color: #666;">기술적 세부사항</summary>
|
|
<pre style="
|
|
background: #f8f9fa;
|
|
padding: 1rem;
|
|
border-radius: 0.5rem;
|
|
margin-top: 1rem;
|
|
overflow-x: auto;
|
|
font-size: 0.875rem;
|
|
">${error.message}</pre>
|
|
</details>
|
|
</div>
|
|
`;
|
|
|
|
container.innerHTML = errorHTML;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 로딩 상태 확인
|
|
* @returns {Object} 로딩 상태 정보
|
|
*/
|
|
getLoadingStatus() {
|
|
const total = this.modules.length;
|
|
const loaded = this.modules.filter(m => m.loaded).length;
|
|
|
|
return {
|
|
total,
|
|
loaded,
|
|
percentage: Math.round((loaded / total) * 100),
|
|
isComplete: loaded === total,
|
|
modules: this.modules.map(m => ({
|
|
name: m.name,
|
|
loaded: m.loaded
|
|
}))
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 특정 모듈 로딩 상태 확인
|
|
* @param {string} moduleName - 모듈명
|
|
* @returns {boolean} 로딩 완료 여부
|
|
*/
|
|
isModuleLoaded(moduleName) {
|
|
const module = this.modules.find(m => m.name === moduleName);
|
|
return module ? module.loaded : false;
|
|
}
|
|
}
|
|
|
|
// 전역 인스턴스 생성
|
|
window.WorkAnalysisModuleLoader = new WorkAnalysisModuleLoader();
|
|
|
|
// 자동 로딩 시작 (DOM이 준비되면)
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
window.WorkAnalysisModuleLoader.loadAll();
|
|
});
|
|
} else {
|
|
// DOM이 이미 준비된 경우 즉시 로딩
|
|
window.WorkAnalysisModuleLoader.loadAll();
|
|
}
|
|
|
|
// Export는 브라우저 환경에서 제거됨
|