import { typeStep2Kor } from '../main.js'; let projectTypeBtn; let projectTypeCapsule; let projectTypeList = null; let projectStepList = null; let mainLayerState = null; // 메인 레이어 상태 // 프로젝트 설정 저장 버튼 클릭 이벤트 document.getElementById('project-save-btn').addEventListener('click', async () => { const projectSaveBtn = document.getElementById('project-save-btn'); const projectStepBtn = document.getElementById('project-step-btn'); const projectNameInput = document.getElementById('project-name-input'); if (projectSaveBtn.textContent === '저장') { // type let typeVal = projectTypeBtn.children[0].textContent; let typeValResult = stepTypeEng(typeVal); // step let stepVal = projectStepBtn.children[0].textContent; let stepValResult = stepTypeEng(stepVal); // project_name let nameVal = projectNameInput.value; let projectInfoParams = { projectId : vars.project.project_id, category : vars.project.category, project_type : typeValResult, step : stepValResult, project_nm : nameVal, } let res = await axios.post('/common/updateProjectInfo', {params: projectInfoParams}); if (res.data.message == 'updateProjectInfo_success') { // 수정된 프로젝트 정보 가져와서 전역변수에 저장 let projectRes = await axios.get('/common/getProject'); for (let project of projectRes.data.data) { vars.allProject[project.project_id] = project; } vars.project = vars.allProject[vars.project_id]; setReadOnlyMode(vars.project.category); } } }); // 프로젝트 설정 취소 클릭 이벤트 document.querySelector('#project-cancel-btn').addEventListener('click', () => { const projectSaveBtn = document.getElementById('project-save-btn'); if (projectSaveBtn.textContent === '저장') projectSaveBtn.textContent = '수정'; const list = document.querySelector('#project-type-wrap-overseas .project-type__list'); list.classList.remove('--project-list__open'); setReadOnlyMode(vars.project.category); }); export function initProjectSetting(param) { const projectSaveBtn = document.getElementById('project-save-btn'); const projectCancelBtn = document.getElementById('project-cancel-btn'); const projectLocationBtn = document.getElementById('project-location-btn'); let projectTypeWrap = document.getElementById('project-type-wrap'); let projectTypeWrapOverseas = document.getElementById('project-type-wrap-overseas'); if (param === undefined) { // overseas, bim 아닌 경우 projectTypeWrap.style.display = 'none'; projectTypeWrapOverseas.style.display = 'none'; projectTypeBtn = document.getElementById('project-type-btn'); projectTypeCapsule = document.getElementById('project-type-capsule'); } else { if (param === 'overseas') { // overseas projectTypeWrap.style.display = 'none'; projectTypeWrapOverseas.style.display = 'flex'; projectTypeBtn = document.getElementById('project-type-btn-overseas'); projectTypeCapsule = document.getElementById('project-type-capsule-overseas'); } else { //bim projectTypeWrap.style.display = 'flex'; projectTypeWrapOverseas.style.display = 'none'; projectTypeBtn = document.getElementById('project-type-btn'); projectTypeCapsule = document.getElementById('project-type-capsule'); } adjustSelectBoxWidth(projectTypeBtn); } setReadOnlyMode(param); // 권한이 있는 경우 저장 버튼 이벤트 추가 if (vars.permission.checkPermission('change-project-btn')) { // 기존 리스너 제거 후 추가 (중복 방지) projectSaveBtn.textContent = '수정'; projectSaveBtn.removeEventListener('click', handleProjectSaveClick); projectSaveBtn.addEventListener('click', () => handleProjectSaveClick(param)); } else { // 권한 없으면 버튼 제거 projectSaveBtn.remove(); projectCancelBtn.remove(); projectLocationBtn.remove(); } // 이벤트 리스너 초기화 initEventListeners(); } function handleProjectSaveClick(param) { const projectSaveBtn = document.getElementById('project-save-btn'); if (projectSaveBtn.textContent === '저장') { // 저장 버튼 클릭 : 읽기 모드로 전환 projectSaveBtn.textContent = '수정'; setReadOnlyMode(param); } else { // 수정 버튼 클릭: 편집 모드로 전환 projectSaveBtn.textContent = '저장'; setEditMode(param); } } // 읽기 모드 : 관리자 이상이면서 읽기모드 or 일반유저 function setReadOnlyMode(param) { const projectStepBtn = document.getElementById('project-step-btn'); const projectStepCapsule = document.getElementById('project-step-capsule'); const projectNameView = document.getElementById('project-name-view'); const projectNameInput = document.getElementById('project-name-input'); const projectSaveBtn = document.getElementById('project-save-btn'); const projectCancelBtn = document.getElementById('project-cancel-btn'); // step - 버튼 숨기고 캡슐 표시 projectStepBtn.style.display = 'none'; projectStepCapsule.style.display = 'flex'; projectStepCapsule.innerHTML = typeStep2Kor(vars.project.step); projectStepCapsule.className = `project-step-capsule --step-capsule__${vars.project.step}`; // type - 버튼 숨기고 캡슐 표시 projectTypeBtn.style.display = 'none'; projectTypeCapsule.style.display = 'flex'; projectTypeCapsule.innerHTML = typeStep2Kor(vars.project.project_type); // name - input 숨기고 view 표시 projectNameInput.style.display = 'none'; projectNameView.style.display = 'flex'; projectNameView.innerHTML = vars.project.short_nm; if(param !== 'overseas' && param !== 'bimproject') { projectStepCapsule.style.display = 'none'; projectTypeCapsule.style.display = 'none'; projectNameView.innerHTML = vars.project.project_nm; projectSaveBtn.style.display = 'none'; projectCancelBtn.style.display = 'none'; } // location - 관리자이상:버튼 o , 관리자이하: 버튼x if (vars.permission.checkPermission('change-project-btn')) { document.querySelector('#project-location-btn').style.display = 'flex'; } const lat = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lat'); lat.innerHTML =`
위도 ${vars.project.lat}
` const lon = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lon'); lon.innerHTML =`
경도 ${vars.project.lon}
` } // 편집모드 : 관리자 이상이면서 편집모드 function setEditMode(param) { const projectStepBtn = document.getElementById('project-step-btn'); const projectStepCapsule = document.getElementById('project-step-capsule'); const projectNameView = document.getElementById('project-name-view'); const projectNameInput = document.getElementById('project-name-input'); // step - 캡슐 숨기고 버튼 표시 projectStepCapsule.style.display = 'none'; projectStepBtn.style.display = 'flex'; projectStepBtn.innerHTML = `
${typeStep2Kor(vars.project.step)}
`; // type - 캡슐 숨기고 버튼 표시 projectTypeCapsule.style.display = 'none'; projectTypeBtn.style.display = 'flex'; projectTypeBtn.innerHTML = `
${typeStep2Kor(vars.project.project_type)}
`; // name - view 숨기고 input 표시 projectNameView.style.display = 'none'; projectNameInput.style.display = 'flex'; projectNameInput.value = projectNameView.textContent; if(param !== 'overseas' && param !== 'bimproject') { projectStepBtn.style.display = 'none'; projectTypeBtn.style.display = 'none'; } // location - 수정 버튼, 위경도 위치 표시 document.querySelector('#project-location-btn').style.display = 'flex'; const lat = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lat'); lat.innerHTML =`
위도 ${vars.project.lat}
` const lon = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lon'); lon.innerHTML =`
경도 ${vars.project.lon}
` } // 접속 인원 모달 - 프로젝트 type, step 변경 이벤트 function initEventListeners() { // project-type-btn 클릭 이벤트 if (projectTypeBtn) { // 기존 이벤트 제거 후 추가 (중복 방지) const newBtn = projectTypeBtn.cloneNode(true); projectTypeBtn.parentNode.replaceChild(newBtn, projectTypeBtn); projectTypeBtn = newBtn; projectTypeList = projectTypeBtn.parentElement.querySelector('.project-type__list'); projectTypeBtn.addEventListener('click', (e) => { e.stopPropagation(); projectTypeList?.classList.toggle('--project-list__open'); }); } // project-step-btn 클릭 이벤트 const projectStepBtn = document.getElementById('project-step-btn'); if (projectStepBtn) { projectStepList = document.querySelector('.project-step__list'); projectStepBtn.addEventListener('click', (e) => { e.stopPropagation(); projectStepList?.classList.toggle('--project-list__open'); }); } // modal-wrap 클릭 이벤트 if (projectTypeBtn) { const modalWrap = projectTypeBtn.closest('.modal-wrap'); if (modalWrap) { modalWrap.addEventListener('click', (e) => { projectTypeList?.classList.remove('--project-list__open'); projectStepList?.classList.remove('--project-list__open'); }); } } // project-type__list_item 클릭 이벤트 if (projectTypeList) { projectTypeList.querySelectorAll('.project-type__list_item').forEach(item => { item.addEventListener('click', async(e) => { e.stopPropagation(); projectTypeList.classList.remove('--project-list__open'); let type = e.target.classList[1].split('__')[1]; let kor = e.target.textContent; projectTypeBtn.innerHTML = `
${kor}
`; }); }); } // project-step__list_item 클릭 이벤트 if (projectStepList) { projectStepList.querySelectorAll('.project-step__list_item').forEach(item => { item.addEventListener('click', async(e) => { e.stopPropagation(); projectStepList.classList.remove('--project-list__open'); let step = e.target.classList[1].split('__')[1]; let btn = document.getElementById('project-step-btn'); let kor = typeStep2Kor(step); if (btn) { btn.innerHTML = `
${kor}
`; } }); }); } } function stepTypeEng(param) { let result = param; switch(param) { case '완료': result = 'done'; break; case '진행': result = 'active'; break; case '중지': result = 'stop'; break; case '대기': result = 'wait'; break; case '시공': result = 'construction'; break; case '설계': result = 'design'; break; case '제안': result = 'surgest'; break; case '연구': result = 'research'; break; case '지원': result = 'support'; break; case '센터': result = 'center'; break; case '측량': result = 'survey'; break; case 'MP (기본계획)': result = 'MP'; break; case 'DD (실시설계)': result = 'DD'; break; case 'FS (타당성조사)': result = 'FS'; break; case 'PD (기본설계)': result = 'PD'; break; case 'DS (설계감리)': result = 'DS'; break; case 'CS (시공감리)': result = 'CS'; break; case 'PMC (실시설계)': result = 'PMC'; break; case 'IDC (타당성조사)': result = 'IDC'; break; case 'DR (설계검토)': result = 'DR'; break; case 'BD (수주영업)': result = 'BD'; break; case 'ETC (기타)': result = 'ETC'; break; default: result = '없음'; break; } return result; } // 셀렉트박스 크기 조정 function adjustSelectBoxWidth(button) { if (!button) return; const list = button.parentElement.querySelector('.project-type__list'); if (!list) return; // canvas를 사용한 텍스트 너비 측정 const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); // 현재 폰트 스타일 가져오기 const computedStyle = window.getComputedStyle(button); context.font =`${computedStyle.fontSize} ${computedStyle.fontFamily}`; let maxWidth = 0; const items = list.querySelectorAll('.project-type__list_item'); items.forEach(item => { const text = item.textContent.trim(); const metrics = context.measureText(text); const width = metrics.width; if (width > maxWidth) { maxWidth = width; } }); // 적용 if (maxWidth > 0) { const finalWidth = maxWidth + 25; // 버튼에 적용 button.style.minWidth = `${finalWidth}px`; button.style.textAlign = 'center'; // 가운데 정렬 button.style.justifyContent = 'center'; // flex인 경우 button.style.display = 'flex'; // flex 적용 button.style.alignItems = 'center'; // 세로 가운데 정렬 // 캡슐에 적용 const capsule = button.parentElement.querySelector('.--type-capsule'); if (capsule) { capsule.style.minWidth = `${finalWidth}px`; capsule.style.textAlign = 'center'; // 가운데 정렬 capsule.style.justifyContent = 'center'; // flex인 경우 capsule.style.display = 'flex'; // flex 적용 capsule.style.alignItems = 'center'; // 세로 가운데 정렬 } // 리스트에 적용 list.style.minWidth = `${finalWidth}px`; // 리스트 글씨 정렬 items.forEach(item => { item.style.paddingLeft = '5px'; item.style.paddingRight = '5px'; }) } } // 프로젝트 위치 수정 버튼 클릭 이벤트 document.getElementById('project-location-btn').addEventListener('click', () => { document.querySelector('.project-location-modal').style.display = 'flex'; openLocationModal(); }) // 지도 모달창 닫기 버튼, 취소 버튼 클릭 이벤트 document.querySelector('.project-location-modal .modal-wrap .modal-head .close').addEventListener('click', () => { closeLocationModal(); }); document.querySelector('.project-location-modal .modal-wrap .modal-foot .button').addEventListener('click', () => { closeLocationModal(); }); // 기본 지도 모달창 버튼 클릭 이벤트 document.querySelector('.project-location-modal .modal-wrap .modal-body .map-wrap .xs-button').addEventListener('click', () => { document.querySelector('.project-location-modal .modal-wrap .modal-body .map-wrap .base-map').style.display = 'flex'; }); // 기본 지도 모달창 닫기 버튼 클릭 이벤트 document.querySelector('.project-location-modal .modal-wrap .modal-body .map-wrap .base-map .text-wrap .close').addEventListener('click', () => { document.querySelector('.project-location-modal .modal-wrap .modal-body .map-wrap .base-map').style.display = 'none'; }); // 지도 모달창 저장 버튼 클릭 이벤트 document.querySelector('.project-location-modal .modal-wrap .modal-foot .primary-button').addEventListener('click', async() => { if(!ol.locationMap || !ol.locationMap.clickCoord) { alert('위치를 선택해주세요'); return; } let updateLocationParams = { projectId: vars.project.project_id, category: vars.project.category, project_nm: vars.project.project_nm, lon: ol.locationMap.clickCoord.lon, lat: ol.locationMap.clickCoord.lat }; let res = await axios.post('/common/updateLocationInfo', {params: updateLocationParams}); if (res.data.message == 'updateLocationInfo_success') { vars.project.lon = res.data.data.lon; vars.project.lat = res.data.data.lat; closeLocationModal(); const lat = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lat'); lat.innerHTML = `
위도 ${res.data.data.lat}
`; const lon = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lon'); lon.innerHTML = `
경도 ${res.data.data.lon}
`; } }) // 프로젝트 위치 수정 function openLocationModal() { // 메인 지도 레이어 상태 백업 if (vars.roadLayer && vars.satelliteLayer && vars.hybridLayer) { mainLayerState = { road: vars.roadLayer.getVisible(), satellite: vars.satelliteLayer.getVisible(), hybrid: vars.hybridLayer.getVisible() }; } initLocationMap(); // 기존 좌표가 있을 때만 블루 마커 생성 if (vars.project.lon && vars.project.lat) { if (!ol.locationMap.blueMarkerOverlay) { // 블루 마커 (저장된 위치) let blueMarker = document.createElement('div'); blueMarker.style.width = '1rem'; blueMarker.style.height = '1rem'; blueMarker.style.backgroundColor = '#0D8DF2'; blueMarker.style.borderRadius = '50%'; blueMarker.style.border = '0.1875rem solid #fff'; blueMarker.style.boxShadow = '0 0.25rem 0.5rem rgba(0, 0, 0, 0.05)'; ol.locationMap.blueMarkerOverlay = new ol.Overlay({ element: blueMarker, positioning: 'center-center', stopEvent: false, zIndex: 9998 }); ol.locationMap.addOverlay(ol.locationMap.blueMarkerOverlay); } if (!ol.locationMap.blueLabelOverlay) { let blueLabel = document.createElement('div'); ol.locationMap.blueLabelOverlay = new ol.Overlay({ element: blueLabel, positioning: 'bottom-center', offset: [0, -10], stopEvent: false, zIndex: 9998, }); ol.locationMap.addOverlay(ol.locationMap.blueLabelOverlay); } const position3857 = ol.proj.fromLonLat([vars.project.lon, vars.project.lat]); ol.locationMap.blueMarkerOverlay.setPosition(position3857); ol.locationMap.blueLabelOverlay.setPosition(position3857); ol.locationMap.blueLabelOverlay.element.innerHTML = `
저장된 위치
경도 : ${vars.project.lon}
위도 : ${vars.project.lat}
`; } } // 지도 초기화 function initLocationMap() { // 위치 모달 지도만 삭제 if (ol.locationMap) { ol.locationMap.getOverlays()?.clear(); ol.locationMap.getLayers()?.forEach(l => { const src = l.getSource?.(); if (src && src instanceof ol.source.Vector) src.clear(true); }); ol.locationMap.getLayers()?.clear(); if (typeof ol.locationMap.dispose === 'function') { ol.locationMap.dispose(); } ol.locationMap = null; } // 위치 설정 모달용 임시 레이어 생성 const tempRoadLayer = new ol.layer.Tile({ source: new ol.source.XYZ({ url: vars.roadLayer.getSource().getUrls()[0] }), visible: mainLayerState?.road ?? true }); const tempSatelliteLayer = new ol.layer.Tile({ source: new ol.source.XYZ({ url: vars.satelliteLayer.getSource().getUrls()[0] }), visible: mainLayerState?.satellite ?? false }); const tempHybridLayer = new ol.layer.Tile({ source: new ol.source.XYZ({ url: vars.hybridLayer.getSource().getUrls()[0] }), visible: mainLayerState?.hybrid ?? false }); ol.locationMap = new ol.Map({ target: 'map-location', layers: [tempRoadLayer, tempSatelliteLayer, tempHybridLayer], view: new ol.View({ projection: 'EPSG:3857', center: ol.proj.fromLonLat([127.8, 35.9]), zoom: 7, constrainResolution: true, smoothResolutionConstraint: true }) }); // 임시 레이어 참조 저장 ol.locationMap.tempRoadLayer = tempRoadLayer; ol.locationMap.tempSatelliteLayer = tempSatelliteLayer; ol.locationMap.tempHybridLayer = tempHybridLayer; // proj4 설정 proj4.defs([ ['EPSG:5185', '+proj=tmerc +lat_0=38 +lon_0=125 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs'], ['EPSG:5186', '+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs'], ['EPSG:5187', '+proj=tmerc +lat_0=38 +lon_0=129 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs'], ['EPSG:5188', '+proj=tmerc +lat_0=38 +lon_0=131 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs'], ['EPSG:4978', '+proj=geocent +datum=WGS84 +units=m +no_defs'], ['EPSG:4326', '+proj=longlat +datum=WGS84 +no_defs'], ]); ol.proj.proj4.register(proj4); // 레드 마커 생성 let marker = document.createElement('div'); marker.classList.add('marker'); marker.style.width = '1rem'; marker.style.height = '1rem'; marker.style.backgroundColor = '#F21D0D'; marker.style.borderRadius = '50%'; marker.style.border = '0.1875rem solid #fff'; marker.style.boxShadow = '0 0.25rem 0.5rem rgba(0, 0, 0, 0.05)'; ol.locationMap.redMarkerOverlay = new ol.Overlay({ element: marker, positioning: 'center-center', stopEvent: false, zIndex: 9999 }); ol.locationMap.addOverlay(ol.locationMap.redMarkerOverlay); let label = document.createElement('div'); ol.locationMap.redLabelOverlay = new ol.Overlay({ element: label, positioning: 'bottom-center', offset: [0, -10], stopEvent: false, zIndex: 9999, }); ol.locationMap.addOverlay(ol.locationMap.redLabelOverlay); // 클릭 이벤트 ol.locationMap.on('click', function(e) { const lonLat = ol.proj.toLonLat(e.coordinate); const lon = lonLat[0].toFixed(6); const lat = lonLat[1].toFixed(6); ol.locationMap.clickCoord = { lon: Number(lon), lat: Number(lat), coordinate3857: e.coordinate }; ol.locationMap.redMarkerOverlay.setPosition(e.coordinate); ol.locationMap.redLabelOverlay.element.innerHTML = `
선택한 위치
경도 : ${lon}
위도 : ${lat}
`; ol.locationMap.redLabelOverlay.setPosition(e.coordinate); }); } // 기본지도 타입 라디오 버튼 클릭 이벤트 document.querySelectorAll('.project-location-modal input[name="location-base-map"]').forEach(radio => { radio.addEventListener('change', function() { if (!ol.locationMap) return; const type = this.value; // 위치 설정 모달의 임시 레이어만 변경 ol.locationMap.tempRoadLayer.setVisible(false); ol.locationMap.tempSatelliteLayer.setVisible(false); ol.locationMap.tempHybridLayer.setVisible(false); switch(type) { case 'road': ol.locationMap.tempRoadLayer.setVisible(true); break; case 'hybrid': ol.locationMap.tempHybridLayer.setVisible(true); break; case 'satellite': ol.locationMap.tempSatelliteLayer.setVisible(true); break; } }); }); // 모달 닫기 함수 function closeLocationModal() { document.querySelector('.project-location-modal').style.display = 'none'; if (ol.locationMap) { ol.locationMap.setTarget(null); if (typeof ol.locationMap.dispose === 'function') { ol.locationMap.dispose(); } ol.locationMap = null; } // 메인 지도 레이어 상태 복원 if (mainLayerState) { vars.roadLayer.setVisible(mainLayerState.road); vars.satelliteLayer.setVisible(mainLayerState.satellite); vars.hybridLayer.setVisible(mainLayerState.hybrid); mainLayerState = null; } }