Files
PM_test/views/main/jsm/archive/projectSetting.js
2026-06-12 17:14:03 +09:00

711 lines
27 KiB
JavaScript

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 =`<div class="project-location-lat">위도 ${vars.project.lat}</div>`
const lon = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lon');
lon.innerHTML =`<div class="project-location-lon">경도 ${vars.project.lon}</div>`
}
// 편집모드 : 관리자 이상이면서 편집모드
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 = `
<h5 class="project-step__label --step__${vars.project.step}">${typeStep2Kor(vars.project.step)}</h5>
<i class="project-step__icon"></i>
`;
// type - 캡슐 숨기고 버튼 표시
projectTypeCapsule.style.display = 'none';
projectTypeBtn.style.display = 'flex';
projectTypeBtn.innerHTML = `
<h5 class="project-type__label --type__${vars.project.project_type}">${typeStep2Kor(vars.project.project_type)}</h5>
<i class="project-type__icon"></i>
`;
// 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 =`<div class="project-location-lat">위도 ${vars.project.lat}</div>`
const lon = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lon');
lon.innerHTML =`<div class="project-location-lon">경도 ${vars.project.lon}</div>`
}
// 접속 인원 모달 - 프로젝트 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 = `
<h5 class="project-type__label --type__${type}">${kor}</h5>
<i class="project-type__icon"></i>`;
});
});
}
// 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 = `
<h5 class="project-step__label --step__${step}">${kor}</h5>
<i class="project-step__icon"></i>`;
}
});
});
}
}
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 = `<div class="project-location-lat">위도 ${res.data.data.lat}</div>`;
const lon = document.querySelector('.archive-modal .wrap .modal-wrap .modal-body .project-setting-wrap .project-location-wrap .project-location-lon');
lon.innerHTML = `<div class="project-location-lon">경도 ${res.data.data.lon}</div>`;
}
})
// 프로젝트 위치 수정
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 = `
<div style="background: #fff; color: #111; padding: 0.25rem 0.5rem; border-radius: 0.25rem; border: 0.1875rem solid #0D8DF2; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.05); font-size: 0.875rem; font-weight: 500; line-height: 1.25rem; letter-spacing: -0.0175rem;">
저장된 위치 <br>
경도 : ${vars.project.lon}<br>
위도 : ${vars.project.lat}
</div>
`;
}
}
// 지도 초기화
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 = `
<div style="background: #fff; color: #111; padding: 0.25rem 0.5rem; border-radius: 0.25rem; border: 0.1875rem solid #F21D0D; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.05); font-size: 0.875rem; font-weight:500; line-height: 1.25rem; letter-spacing: -0.0175rem;">
선택한 위치 <br>
경도 : ${lon} <br>
위도 : ${lat}
</div>
`;
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;
}
}