feat: 다수 기능 개선 - 순찰, 출근, 작업분석, 모바일 UI 등
- 순찰/점검 기능 개선 (zone-detail 페이지 추가) - 출근/근태 시스템 개선 (연차 조회, 근무현황) - 작업분석 대분류 그룹화 및 마이그레이션 스크립트 - 모바일 네비게이션 UI 추가 - NAS 배포 도구 및 문서 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
284
deploy/tkfb-package/web-ui/js/workplace-management/state.js
Normal file
284
deploy/tkfb-package/web-ui/js/workplace-management/state.js
Normal file
@@ -0,0 +1,284 @@
|
||||
/**
|
||||
* Workplace Management - State Manager
|
||||
* 작업장 관리 페이지의 전역 상태 관리
|
||||
*/
|
||||
|
||||
class WorkplaceState {
|
||||
constructor() {
|
||||
// 마스터 데이터
|
||||
this.categories = [];
|
||||
this.workplaces = [];
|
||||
this.allEquipments = [];
|
||||
this.existingEquipments = [];
|
||||
|
||||
// 현재 상태
|
||||
this.currentCategoryId = '';
|
||||
this.currentEditingCategory = null;
|
||||
this.currentEditingWorkplace = null;
|
||||
this.currentWorkplaceMapId = null;
|
||||
|
||||
// 작업장 지도 관련
|
||||
this.workplaceCanvas = null;
|
||||
this.workplaceCtx = null;
|
||||
this.workplaceImage = null;
|
||||
this.workplaceIsDrawing = false;
|
||||
this.workplaceStartX = 0;
|
||||
this.workplaceStartY = 0;
|
||||
this.workplaceCurrentRect = null;
|
||||
this.workplaceEquipmentRegions = [];
|
||||
|
||||
// 전체화면 편집기 관련
|
||||
this.fsCanvas = null;
|
||||
this.fsCtx = null;
|
||||
this.fsImage = null;
|
||||
this.fsIsDrawing = false;
|
||||
this.fsStartX = 0;
|
||||
this.fsStartY = 0;
|
||||
this.fsCurrentRect = null;
|
||||
this.fsSidebarVisible = true;
|
||||
|
||||
// 리스너
|
||||
this.listeners = new Map();
|
||||
|
||||
console.log('[WorkplaceState] 초기화 완료');
|
||||
}
|
||||
|
||||
/**
|
||||
* 상태 업데이트
|
||||
*/
|
||||
update(key, value) {
|
||||
const prevValue = this[key];
|
||||
this[key] = value;
|
||||
this.notifyListeners(key, value, prevValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 리스너 등록
|
||||
*/
|
||||
subscribe(key, callback) {
|
||||
if (!this.listeners.has(key)) {
|
||||
this.listeners.set(key, []);
|
||||
}
|
||||
this.listeners.get(key).push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 리스너 알림
|
||||
*/
|
||||
notifyListeners(key, newValue, prevValue) {
|
||||
const keyListeners = this.listeners.get(key) || [];
|
||||
keyListeners.forEach(callback => {
|
||||
try {
|
||||
callback(newValue, prevValue);
|
||||
} catch (error) {
|
||||
console.error(`[WorkplaceState] 리스너 오류 (${key}):`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 카테고리 변경
|
||||
*/
|
||||
setCurrentCategory(categoryId) {
|
||||
const prevId = this.currentCategoryId;
|
||||
this.currentCategoryId = categoryId === '' ? '' : categoryId;
|
||||
this.notifyListeners('currentCategoryId', this.currentCategoryId, prevId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 카테고리 정보 가져오기
|
||||
*/
|
||||
getCurrentCategory() {
|
||||
if (!this.currentCategoryId) return null;
|
||||
return this.categories.find(c => c.category_id == this.currentCategoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 카테고리별 작업장 가져오기
|
||||
*/
|
||||
getFilteredWorkplaces() {
|
||||
if (this.currentCategoryId === '') {
|
||||
return this.workplaces;
|
||||
}
|
||||
return this.workplaces.filter(w => w.category_id == this.currentCategoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업장 지도 상태 초기화
|
||||
*/
|
||||
resetWorkplaceMapState() {
|
||||
this.workplaceCanvas = null;
|
||||
this.workplaceCtx = null;
|
||||
this.workplaceImage = null;
|
||||
this.workplaceIsDrawing = false;
|
||||
this.workplaceCurrentRect = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체화면 편집기 상태 초기화
|
||||
*/
|
||||
resetFullscreenState() {
|
||||
this.fsCanvas = null;
|
||||
this.fsCtx = null;
|
||||
this.fsImage = null;
|
||||
this.fsIsDrawing = false;
|
||||
this.fsCurrentRect = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 통계 계산
|
||||
*/
|
||||
getStatistics() {
|
||||
const total = this.workplaces.length;
|
||||
const active = this.workplaces.filter(w =>
|
||||
w.is_active === 1 || w.is_active === true
|
||||
).length;
|
||||
const factoryTotal = this.categories.length;
|
||||
|
||||
const filtered = this.getFilteredWorkplaces();
|
||||
const filteredActive = filtered.filter(w =>
|
||||
w.is_active === 1 || w.is_active === true
|
||||
).length;
|
||||
|
||||
return {
|
||||
total,
|
||||
active,
|
||||
factoryTotal,
|
||||
filteredTotal: filtered.length,
|
||||
filteredActive
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 상태 초기화
|
||||
*/
|
||||
reset() {
|
||||
this.currentEditingCategory = null;
|
||||
this.currentEditingWorkplace = null;
|
||||
this.currentWorkplaceMapId = null;
|
||||
this.resetWorkplaceMapState();
|
||||
this.resetFullscreenState();
|
||||
}
|
||||
|
||||
/**
|
||||
* 디버그 출력
|
||||
*/
|
||||
debug() {
|
||||
console.log('[WorkplaceState] 현재 상태:', {
|
||||
categories: this.categories.length,
|
||||
workplaces: this.workplaces.length,
|
||||
currentCategoryId: this.currentCategoryId,
|
||||
allEquipments: this.allEquipments.length,
|
||||
workplaceEquipmentRegions: this.workplaceEquipmentRegions.length
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 전역 인스턴스 생성
|
||||
window.WorkplaceState = new WorkplaceState();
|
||||
|
||||
// 하위 호환성을 위한 전역 변수 프록시
|
||||
const wpStateProxy = window.WorkplaceState;
|
||||
|
||||
Object.defineProperties(window, {
|
||||
categories: {
|
||||
get: () => wpStateProxy.categories,
|
||||
set: (v) => { wpStateProxy.categories = v; }
|
||||
},
|
||||
workplaces: {
|
||||
get: () => wpStateProxy.workplaces,
|
||||
set: (v) => { wpStateProxy.workplaces = v; }
|
||||
},
|
||||
currentCategoryId: {
|
||||
get: () => wpStateProxy.currentCategoryId,
|
||||
set: (v) => { wpStateProxy.currentCategoryId = v; }
|
||||
},
|
||||
currentEditingCategory: {
|
||||
get: () => wpStateProxy.currentEditingCategory,
|
||||
set: (v) => { wpStateProxy.currentEditingCategory = v; }
|
||||
},
|
||||
currentEditingWorkplace: {
|
||||
get: () => wpStateProxy.currentEditingWorkplace,
|
||||
set: (v) => { wpStateProxy.currentEditingWorkplace = v; }
|
||||
},
|
||||
workplaceCanvas: {
|
||||
get: () => wpStateProxy.workplaceCanvas,
|
||||
set: (v) => { wpStateProxy.workplaceCanvas = v; }
|
||||
},
|
||||
workplaceCtx: {
|
||||
get: () => wpStateProxy.workplaceCtx,
|
||||
set: (v) => { wpStateProxy.workplaceCtx = v; }
|
||||
},
|
||||
workplaceImage: {
|
||||
get: () => wpStateProxy.workplaceImage,
|
||||
set: (v) => { wpStateProxy.workplaceImage = v; }
|
||||
},
|
||||
workplaceIsDrawing: {
|
||||
get: () => wpStateProxy.workplaceIsDrawing,
|
||||
set: (v) => { wpStateProxy.workplaceIsDrawing = v; }
|
||||
},
|
||||
workplaceStartX: {
|
||||
get: () => wpStateProxy.workplaceStartX,
|
||||
set: (v) => { wpStateProxy.workplaceStartX = v; }
|
||||
},
|
||||
workplaceStartY: {
|
||||
get: () => wpStateProxy.workplaceStartY,
|
||||
set: (v) => { wpStateProxy.workplaceStartY = v; }
|
||||
},
|
||||
workplaceCurrentRect: {
|
||||
get: () => wpStateProxy.workplaceCurrentRect,
|
||||
set: (v) => { wpStateProxy.workplaceCurrentRect = v; }
|
||||
},
|
||||
workplaceEquipmentRegions: {
|
||||
get: () => wpStateProxy.workplaceEquipmentRegions,
|
||||
set: (v) => { wpStateProxy.workplaceEquipmentRegions = v; }
|
||||
},
|
||||
existingEquipments: {
|
||||
get: () => wpStateProxy.existingEquipments,
|
||||
set: (v) => { wpStateProxy.existingEquipments = v; }
|
||||
},
|
||||
allEquipments: {
|
||||
get: () => wpStateProxy.allEquipments,
|
||||
set: (v) => { wpStateProxy.allEquipments = v; }
|
||||
},
|
||||
fsCanvas: {
|
||||
get: () => wpStateProxy.fsCanvas,
|
||||
set: (v) => { wpStateProxy.fsCanvas = v; }
|
||||
},
|
||||
fsCtx: {
|
||||
get: () => wpStateProxy.fsCtx,
|
||||
set: (v) => { wpStateProxy.fsCtx = v; }
|
||||
},
|
||||
fsImage: {
|
||||
get: () => wpStateProxy.fsImage,
|
||||
set: (v) => { wpStateProxy.fsImage = v; }
|
||||
},
|
||||
fsIsDrawing: {
|
||||
get: () => wpStateProxy.fsIsDrawing,
|
||||
set: (v) => { wpStateProxy.fsIsDrawing = v; }
|
||||
},
|
||||
fsStartX: {
|
||||
get: () => wpStateProxy.fsStartX,
|
||||
set: (v) => { wpStateProxy.fsStartX = v; }
|
||||
},
|
||||
fsStartY: {
|
||||
get: () => wpStateProxy.fsStartY,
|
||||
set: (v) => { wpStateProxy.fsStartY = v; }
|
||||
},
|
||||
fsCurrentRect: {
|
||||
get: () => wpStateProxy.fsCurrentRect,
|
||||
set: (v) => { wpStateProxy.fsCurrentRect = v; }
|
||||
},
|
||||
fsSidebarVisible: {
|
||||
get: () => wpStateProxy.fsSidebarVisible,
|
||||
set: (v) => { wpStateProxy.fsSidebarVisible = v; }
|
||||
}
|
||||
});
|
||||
|
||||
// currentWorkplaceMapId를 window에도 설정
|
||||
Object.defineProperty(window, 'currentWorkplaceMapId', {
|
||||
get: () => wpStateProxy.currentWorkplaceMapId,
|
||||
set: (v) => { wpStateProxy.currentWorkplaceMapId = v; }
|
||||
});
|
||||
|
||||
console.log('[Module] workplace-management/state.js 로드 완료');
|
||||
Reference in New Issue
Block a user