Przeglądaj źródła

2024-03-20 update

junggilpark 1 rok temu
rodzic
commit
b8446e76ec

+ 4 - 0
pom.xml

@@ -232,6 +232,10 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web-services</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.aspectj</groupId>
             <artifactId>aspectjrt</artifactId>

+ 15 - 0
src/main/java/com/its/web/exception/ExceptionContollerAdvisor.java

@@ -100,6 +100,21 @@ public class ExceptionContollerAdvisor {
         return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
     }
 
+    @ExceptionHandler(NumberFormatException.class)
+    public ResponseEntity<ErrorResponse> numberFormatExceptionHandler(HttpServletRequest request, final NumberFormatException ex) {
+        List<String> errorList = new ArrayList<>(Collections.singletonList(ex.getMessage()));
+        ErrorResponse response = ErrorResponse.builder()
+                .timestamp(LocalDateTime.now())
+                .status(HttpStatus.EXPECTATION_FAILED.value())
+                .title("NumberFormatException")
+                .message(ex.getMessage())
+                .path(request.getRequestURI())
+                .errors(errorList)
+                .build();
+        log.error("{}", response.toString());
+        return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
+    }
+
     @ExceptionHandler(RuntimeException.class)
     public ResponseEntity<ErrorResponse> exceptionHandler(HttpServletRequest request, final RuntimeException ex) {
         List<String> errorList = new ArrayList<>(Collections.singletonList(ex.getMessage()));

+ 4 - 1
src/main/java/com/its/web/pagination/Pagination.java

@@ -20,6 +20,9 @@ public class Pagination {
     private List<?> list;
 
     public Pagination (String page, int totalCount, String searchType, String searchText) {
+        if (page == null) {
+            page = "1";
+        }
         this.currentPage = 1;
         this.startPage = 1;
         this.endPage = 1;
@@ -43,7 +46,7 @@ public class Pagination {
             }
         }
         catch (NumberFormatException e) {
-            throw new NumberFormatException("This Page Value Is Invalid. Page : "+ page);
+            throw new NumberFormatException("잘못된 페이지 번호입니다. 페이지 번호를 확인해주세요. : "+ page);
         }
 
         if (totalCount > PAGE_PER_NUM){

+ 2 - 6
src/main/java/com/its/web/service/notice/NoticeService.java

@@ -144,8 +144,6 @@ public class NoticeService {
             }
         }
 
-//        resultMap.put("message", message);
-//        resultMap.put("success", success);
         return CommonUtil.getResultDto(success, message);
     }
 
@@ -189,8 +187,6 @@ public class NoticeService {
             }
         }
 
-//        resultMap.put("message", message);
-//        resultMap.put("success", success);
         return CommonUtil.getResultDto(success, message);
     }
 
@@ -263,9 +259,9 @@ public class NoticeService {
                 }
                 os.flush();
             } catch (IOException e) {
-                log.error("noticeImgupload() IO Exception");
+                log.error("IO Exception - noticeImageUpload");
             } catch (Exception e1) {
-                log.error("noticeImgupload() Exception");
+                log.error("Exception - noticeImageUpload");
             }
             finally {
                 if(os != null) {

BIN
src/main/resources/favicon.ico


BIN
src/main/resources/static/images/favicon/android-icon-192x192.png


BIN
src/main/resources/static/images/favicon/apple-icon-114x114.png


BIN
src/main/resources/static/images/favicon/apple-icon-120x120.png


BIN
src/main/resources/static/images/favicon/apple-icon-144x144.png


BIN
src/main/resources/static/images/favicon/apple-icon-152x152.png


BIN
src/main/resources/static/images/favicon/apple-icon-180x180.png


BIN
src/main/resources/static/images/favicon/apple-icon-57x57.png


BIN
src/main/resources/static/images/favicon/apple-icon-60x60.png


BIN
src/main/resources/static/images/favicon/apple-icon-72x72.png


BIN
src/main/resources/static/images/favicon/apple-icon-76x76.png


BIN
src/main/resources/static/images/favicon/favicon-16x16.png


BIN
src/main/resources/static/images/favicon/favicon-32x32.png


BIN
src/main/resources/static/images/favicon/favicon-96x96.png


+ 11 - 0
src/main/resources/static/images/favicon/manifest.json

@@ -0,0 +1,11 @@
+{
+  "name": "App",
+  "icons": [
+    {
+      "src": "\/android-icon-192x192.png",
+      "sizes": "192x192",
+      "type": "image\/png",
+      "density": "4.0"
+    }
+  ]
+}

+ 245 - 260
src/main/resources/static/js/traffic/traffic.js

@@ -1,5 +1,4 @@
 let _size  = [48, 48, 48, 48, 40, 32, 24, 22, 20, 18, 18];
-let _AtrdData = [];
 let _AtrdMap = new Map();
 let selectIncidentId = null;
 
@@ -42,10 +41,8 @@ $(()=>{
 
     // 시설물 유형 정보로 flag 값 세팅
     if (_type) {
-        const listMarkerInfo = _MarkerHandle.findMarkerInfo(_type);
-        listMarkerInfo.isDraw = true;
-        listMarkerInfo.isDrawList = true;
-
+        _MarkerHandle.setIsDraw(_type, true);
+        _MarkerHandle.setIsDrawList(_type, true);
         _methodMap.get(_type)();
     }
 
@@ -282,7 +279,7 @@ $(()=>{
                     if (minX && minY && maxX && maxY) {
                         bounds.extend(new kakao.maps.LatLng(minY, minX));
                         bounds.extend(new kakao.maps.LatLng(maxY, maxX));
-                        _MapHandler.map.setBounds(bounds);
+                        _MapHandler.setBounds(bounds);
                         $('.list-content.spot').html(str);
                         getVertex();
                     }
@@ -301,8 +298,8 @@ $(()=>{
 function moveLocation(xCoordinate, yCoordinate, listIndex) {
     const position = getKakaoPosition(yCoordinate, xCoordinate);
 
-    _MapHandler.map.setCenter(position);
-    _MapHandler.map.setLevel(3);
+    _MapHandler.setCenter(position);
+    _MapHandler.setLevel(3);
     $('.list-content.spot > li.click').removeClass('click');
     $('#spot-' +listIndex).addClass('click');
     getVertex();
@@ -413,9 +410,11 @@ function getAtrd() {
                 if (list && list.length === 2) {
                     const upHill   = list[list.findIndex(obj => obj.drct_cd === '0')];
                     const downHill = list[list.findIndex(obj => obj.drct_cd === '1')];
+                    const upHillId   = upHill.atrd_id;
+                    const downHillId = downHill.atrd_id;
 
-                    listStr += `<li id="atrd_${upHill.atrd_id}_${downHill.atrd_id}" onclick="atrdClickEvent('${upHill.atrd_id}', '${downHill.atrd_id}')">${key}</li>`
-                    mobileStr += `<option value="${upHill.atrd_id}_${downHill.atrd_id}">${key}</option>`
+                    listStr += `<li id="atrd_${upHillId}_${downHillId}" onclick="atrdClickEvent('${upHillId}', '${downHillId}')">${key}</li>`
+                    mobileStr += `<option value="${upHillId}_${downHillId}">${key}</option>`
                 }
             }
             const $mobileSelect = $('.mobile-select');
@@ -468,8 +467,8 @@ function getVertex() {
         _MarkerHandle.findMarkerArr('traffic').markers = [];
     }
 
-    let level = _MapHandler.map.getLevel();
-    const bounds = _MapHandler.map.getBounds();
+    let level = _MapHandler.getLevel();
+    const bounds = _MapHandler.getBounds();
     const swLatLng = bounds.getSouthWest();
     const neLatLng = bounds.getNorthEast();
     const data = {
@@ -528,7 +527,6 @@ function atrdClickEvent(AupHillId, AdownHillId) {
         })
     }
     _MarkerHandle.selectedAtrd = [];
-    _AtrdData = [];
     const isDrawList = _MarkerHandle.isDrawList('traffic');
     const $selectedLi = $('.left-list-area .list-content.list > li.click');
     if (isDrawList && $selectedLi) {
@@ -551,7 +549,7 @@ function atrdClickEvent(AupHillId, AdownHillId) {
         bounds.extend(new kakao.maps.LatLng(upHill.prop.y_crdn_max, upHill.prop.x_crdn_max));
         bounds.extend(new kakao.maps.LatLng(downHill.prop.y_crdn_min, downHill.prop.x_crdn_min));
         bounds.extend(new kakao.maps.LatLng(downHill.prop.y_crdn_max, downHill.prop.x_crdn_max));
-        _MapHandler.map.setBounds(bounds);
+        _MapHandler.setBounds(bounds);
         let boundAfterLevel = getAtrdLevel(_Level);
 
         _MarkerHandle.selectedAtrd = [AupHillId + '_0_' + boundAfterLevel, AdownHillId + '_1_' + boundAfterLevel];
@@ -593,7 +591,6 @@ class MarkerObj {
 
     init () {
         const position = getKakaoPosition(this.Y_CRDN, this.X_CRDN);
-        this.iwContent = this.getIwContent();
         if (this.type !== 'intersectionCamera') {
             const imageLocation = this.image + this.imageType + '.png';
             const { imageSize, imageOption } = this.getImageOptions();
@@ -617,10 +614,10 @@ class MarkerObj {
             const angle = Number(this.prop.cmra_angn);
             content.css(
                 {
-                    width: '38.45px',
-                    height: '38.45px',
+                    width: '48px',
+                    height: '48px',
                     backgroundImage:'url(/images/icon/intersection-cctv.png)',
-                    backgroundSize : '38.45px 38.45px',
+                    backgroundSize : '48px 48px',
                     backgroundRepeat: 'no-repeat',
                     backgroundPosition : 'center',
                     transform : 'rotate(' + angle +'deg)'
@@ -648,7 +645,7 @@ class MarkerObj {
                 name : this.NAME,
             });
 
-            if (_Level <= 2 && _MarkerHandle.findMarkerInfo('intersectionCamera').isDraw){
+            if (_Level <= 2 && _MarkerHandle.isDraw('intersectionCamera')){
                 marker.setMap(_MapHandler.map);
                 this.polyLine.setMap(_MapHandler.map);
             }
@@ -686,137 +683,11 @@ class MarkerObj {
         return {imageSize : imageSize, imageOption : imageOption};
     }
 
-    getIwContent() {
-        let iwContent = null;
-        const {type, ID, NAME, prop} = this;
-        switch (type) {
-            case 'cctv' :
-            case 'intersectionCamera':
-                iwContent =
-                    `<div class="cctv-info-window">
-                        <div class="title">
-                            <div class="cctv-name-${ID}">${NAME}</div>
-                            <div onclick="infoWindowEvent('${type}', '${ID}', 'close')">X</div>
-                        </div>
-                        <div class="content">
-                            <div>
-                                <video id="video-${ID}" class="video-js" playsinline style="width: 100%; height: 100%;"></video>
-                            </div>
-                            <div>
-                                <div>※ CCTV영상은 30초간 제공됩니다.</div>
-                                <div class="continue-play">계속재생</div>
-                            </div>
-                        </div>
-                    </div>`;
-                break;
-            case 'vms' :
-                this.phaseArray = [];
-
-                let isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
-                const WH = vmsWHMap.get(prop.vms_type_cd);
-                let width = 256;
-                let height = 50;
-
-                if (WH) {
-                    width = WH.width;
-                    height = WH.height
-                }
-
-                const msg = prop.msg;
-                let content = "";
-                if (msg && msg.length > 0) {
-                    const windowHeight = $(window).height();
-                    if (isMobile || windowHeight < 900) {
-                        width = WH.width/2;
-                        height = WH.height/2;
-                    }
-
-                    for (let idx in msg) {
-                        let msgObj = msg[idx];
-                        let className = '';
-                        if (idx === "0") {
-                            className = 'active'
-                        }
-                        content += `<img id="phase-${msgObj.phase}" class="${className}" style="width: ${width}; height: ${height};" 
-                                         src="/api/traffic/vms-dspl-image/${this.ID}/${msgObj.phase}" alt="VMS 표출 이미지">`;
-                        this.phaseArray.push(msgObj.phase);
-                    }
-                }
-                else {
-                    width = 256;
-                    height = 50;
-                    content += '표출 이미지 데이터가 없습니다.';
-                }
-                width = width +'px';
-                height = height + 'px';
-
-                iwContent =
-                    `<div class="vms-info-window" style="width: calc(${width} + 10px); height: calc(${height} + 50px);">
-                        <div class="title">
-                            <div class="vms-name-${ID}">${NAME}</div>
-                            <div onclick="infoWindowEvent('vms', ${ID}, 'close')">X</div>
-                        </div>
-                        <div class="content" style="width: ${width}; height: ${height};">
-                            ${content}
-                        </div>
-                    </div>`;
-                break;
-            case 'incident' :
-                iwContent =
-                    `<div class="incident-info-window">
-                        <div class="title">
-                            <div class="incident-name-${ID}">${NAME}</div>
-                            <div onclick="infoWindowEvent('incident', '${ID}', 'close')">X</div>
-                        </div>
-                        <div class="content">
-                            <div>
-                                위치 : ${prop.road_nm}
-                            </div>
-                            <div>
-                                설명 : ${prop.incd_expl}
-                            </div>
-                            <div>
-                                기간 : ${prop.incd_strt_dt} ~ ${prop.incd_end_prar_dt}
-                            </div>
-                        </div>
-                    </div>`;
-                break;
-            case 'parking' :
-                iwContent =
-                    `<div class="parking-info-window">
-                        <div class="title">
-                            <div class="parking-name-${ID}">${NAME}</div>
-                            <div onclick="infoWindowEvent('parking', '${ID}', 'close')"></div>
-                        </div>
-                        <div class="content">
-                            <div class="row">
-                                <div>주차면수</div>
-                                <div title="주차면수 : ${prop.parking_num} 대">${prop.parking_num} 대</div>
-                            </div>
-                            <div class="row">
-                                <div>구분</div>
-                                <div title="구분 : ${prop.parking_type_desc}">${prop.parking_type_desc}</div>
-                            </div>
-                            <div class="row">
-                                <div>기본요금</div>
-                                <div title="기본요금 : ${prop.parking_fee_type_desc}">${prop.parking_fee_type_desc}</div>
-                            </div>
-                            <div class="row">
-                                <div>주소</div>
-                                <div title="주소 : ${prop.parking_addr}">${prop.parking_addr}</div>
-                            </div>
-                        </div>
-                    </div>`;
-                break;
-        }
-        return iwContent;
-    }
-
     click() {
         const selectObj = _MarkerHandle.selectedMarker;
         if (selectObj) {
             if (selectObj === this) {
-                if (selectObj !== 'intersection' || (selectObj === 'intersection' && _Level > 2)) {
+                if (selectObj.type !== 'intersection' || (selectObj.type === 'intersection' && _Level <= 2)) {
                     return;
                 }
             }
@@ -825,7 +696,7 @@ class MarkerObj {
             selectObj.close();
         }
 
-        if (this.type === 'intersectionCamera' && _MarkerHandle.findMarkerInfo('intersection').isDrawList) {
+        if (this.type === 'intersectionCamera' && _MarkerHandle.isDrawList('intersection')) {
             const ixrId = this.prop.ixr_id;
             const ixrLi = $('#intersection-' + ixrId);
             ixrLi.addClass('click');
@@ -840,9 +711,9 @@ class MarkerObj {
         if (this.type === 'intersection') {
             level = 2;
         }
-        const map = _MapHandler.map;
-        map.setLevel(level);
-        map.setCenter(center);
+
+        _MapHandler.setLevel(level);
+        _MapHandler.setCenter(center);
 
         if (this.iwContent) {
             this.infoWindow = $(this.iwContent);
@@ -874,16 +745,17 @@ class MarkerObj {
 
         this.isClick = true;
 
-        const selectMarkers = _MarkerHandle.findMarkerInfo(this.type);
-        if (selectMarkers.isDrawList) {
-            moveToScroll(true, selectMarkers.markers, this.ID); // 클릭 시 리스트 이동
+        if (_MarkerHandle.isDrawList(this.type)) {
+            const markerArr = _MarkerHandle.findMarkerArr(this.type);
+            moveToScroll(true, markerArr, this.ID); // 클릭 시 리스트 이동
         }
 
     }
 
     close() {
         if (this.timer) { // 인터벌이 있는 경우
-            setTimeout(this.timer);
+            clearInterval(this.timer);
+            clearTimeout(this.timer);
             this.timer = null;
         }
         if (this.imageOnOff.includes(this.type)) {// 클릭 이미지가 있는 경우
@@ -892,6 +764,7 @@ class MarkerObj {
 
         let oldPlayer = document.getElementById("video-" + this.ID);
         if (oldPlayer) { // video 태그가 있는 경우
+
             videojs(oldPlayer).dispose();
         }
 
@@ -901,8 +774,7 @@ class MarkerObj {
         }
         const mobilSelect = $('.mobile-select');
 
-        const selectTypes = _MarkerHandle.findMarkerInfo(this.type);
-        if (mobilSelect[0] && selectTypes.isDrawList) { // 리스트가 있는 경우
+        if (mobilSelect[0] && _MarkerHandle.isDrawList(this.type)) { // 리스트가 있는 경우
             mobilSelect.val("-");
             let selectedLi   = $("#" + this.type + "-" + this.ID);
 
@@ -911,7 +783,7 @@ class MarkerObj {
             }
         }
 
-        if (this.type === 'intersectionCamera' && _MarkerHandle.findMarkerInfo('intersection').isDrawList) {
+        if (this.type === 'intersectionCamera' && _MarkerHandle.isDrawList('intersection')) {
             mobilSelect.val("-");
             let selectedId = _MarkerHandle.selectedMarker.prop.ixr_id;
             let selectedLi   = $("#intersection-" + selectedId);
@@ -1078,7 +950,7 @@ class TbAtrdObj extends MarkerObj{
     constructor(obj) {
         super({
             ID : obj.ID,
-            NAME : obj.atrd_nm,
+            NAME : obj.atrd_nm + ' ['+ obj.drct_nm + ']',
             X_CRDN : obj.x_crdn_arr.split(",")[0],
             Y_CRDN : obj.y_crdn_arr.split(",")[0],
             URL    : null,
@@ -1106,8 +978,30 @@ class TbCCtvObj extends MarkerObj{
             IMAGE_TYPE : '1',
             IMAGE : '/images/icon/cctv'
         });
+        this.iwContent = this.getIwContent();
     }
 
+    getIwContent() {
+        const {ID, NAME, type} = this;
+        let iwContent =
+            `<div class="cctv-info-window">
+                        <div class="title">
+                            <div class="cctv-name-${ID}">${NAME}</div>
+                            <div onclick="infoWindowEvent('${type}', '${ID}', 'close')">X</div>
+                        </div>
+                        <div class="content">
+                            <div>
+                                <video id="video-${ID}" class="video-js" style="width: 100%; height: 100%;"></video>
+                            </div>
+                            <div>
+                                <div>※ CCTV영상은 30초간 제공됩니다.</div>
+                                <div class="continue-play">계속재생</div>
+                            </div>
+                        </div>
+                    </div>`;
+
+        return iwContent;
+    }
 }
 /**
  * Parking Object
@@ -1125,6 +1019,37 @@ class TbParkingObj extends MarkerObj{
             IMAGE_TYPE : '1',
             IMAGE : '/images/icon/parking'
         })
+        this.iwContent = this.getIwContent();
+    }
+
+    getIwContent() {
+        const {ID, NAME, prop} = this;
+        let iwContent =
+            `<div class="parking-info-window">
+                        <div class="title">
+                            <div class="parking-name-${ID}">${NAME}</div>
+                            <div onclick="infoWindowEvent('parking', '${ID}', 'close')"></div>
+                        </div>
+                        <div class="content">
+                            <div class="row">
+                                <div>주차면수</div>
+                                <div title="주차면수 : ${prop.parking_num} 대">${prop.parking_num} 대</div>
+                            </div>
+                            <div class="row">
+                                <div>구분</div>
+                                <div title="구분 : ${prop.parking_type_desc}">${prop.parking_type_desc}</div>
+                            </div>
+                            <div class="row">
+                                <div>기본요금</div>
+                                <div title="기본요금 : ${prop.parking_fee_type_desc}">${prop.parking_fee_type_desc}</div>
+                            </div>
+                            <div class="row">
+                                <div>주소</div>
+                                <div title="주소 : ${prop.parking_addr}">${prop.parking_addr}</div>
+                            </div>
+                        </div>
+                    </div>`;
+        return iwContent;
     }
 }
 
@@ -1144,6 +1069,62 @@ class TbVmsObj extends MarkerObj{
               IMAGE_TYPE : '1',
               IMAGE : '/images/icon/vms'
         });
+        this.iwContent = this.getIwContent();
+    }
+
+    getIwContent() {
+        const {ID, NAME, prop} = this;
+        this.phaseArray = [];
+
+        let isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
+        const WH = vmsWHMap.get(prop.vms_type_cd);
+        let width = 256;
+        let height = 50;
+
+        if (WH) {
+            width = WH.width;
+            height = WH.height
+        }
+
+        const msg = prop.msg;
+        let content = "";
+        if (msg && msg.length > 0) {
+            const windowHeight = $(window).height();
+            if (isMobile || windowHeight < 900) {
+                width = WH.width/2;
+                height = WH.height/2;
+            }
+
+            for (let idx in msg) {
+                let msgObj = msg[idx];
+                let className = '';
+                if (idx === "0") {
+                    className = 'active'
+                }
+                content += `<img id="phase-${msgObj.phase}" class="${className}" style="width: ${width}; height: ${height};" 
+                                         src="/api/traffic/vms-dspl-image/${ID}/${msgObj.phase}" alt="VMS 표출 이미지">`;
+                this.phaseArray.push(msgObj.phase);
+            }
+        }
+        else {
+            width = 256;
+            height = 50;
+            content += '표출 이미지 데이터가 없습니다.';
+        }
+        width = width +'px';
+        height = height + 'px';
+
+        let iwContent =
+            `<div class="vms-info-window" style="width: calc(${width} + 10px); height: calc(${height} + 50px);">
+                        <div class="title">
+                            <div class="vms-name-${ID}">${NAME}</div>
+                            <div onclick="infoWindowEvent('vms', ${ID}, 'close')">X</div>
+                        </div>
+                        <div class="content" style="width: ${width}; height: ${height};">
+                            ${content}
+                        </div>
+                    </div>`;
+        return iwContent;
     }
 }
 
@@ -1163,6 +1144,30 @@ class TbIncdObj extends MarkerObj{
             IMAGE_TYPE : '1',
             IMAGE : '/images/icon/incd'
         })
+        this.iwContent = this.getIwContent();
+    }
+
+    getIwContent() {
+        const {ID, NAME, prop} = this;
+        let iwContent =
+            `<div class="incident-info-window">
+                <div class="title">
+                    <div class="incident-name-${ID}">${NAME}</div>
+                    <div onclick="infoWindowEvent('incident', '${ID}', 'close')">X</div>
+                </div>
+                <div class="content">
+                    <div>
+                        위치 : ${prop.road_nm}
+                    </div>
+                    <div>
+                        설명 : ${prop.incd_expl}
+                    </div>
+                    <div>
+                        기간 : ${prop.incd_strt_dt} ~ ${prop.incd_end_prar_dt}
+                    </div>
+                </div>
+            </div>`;
+        return iwContent;
     }
 }
 
@@ -1203,6 +1208,29 @@ class IntersectionCameraObj extends MarkerObj{
                 IMAGE : '/images/icon/intersection'
             }
         )
+        this.iwContent = this.getIwContent();
+    }
+
+    getIwContent() {
+        const {ID, NAME, type} = this;
+        let iwContent =
+            `<div class="cctv-info-window">
+                        <div class="title">
+                            <div class="cctv-name-${ID}">${NAME}</div>
+                            <div onclick="infoWindowEvent('${type}', '${ID}', 'close')">X</div>
+                        </div>
+                        <div class="content">
+                            <div>
+                                <video id="video-${ID}" class="video-js" playsinline style="width: 100%; height: 100%;"></video>
+                            </div>
+                            <div>
+                                <div>※ CCTV영상은 30초간 제공됩니다.</div>
+                                <div class="continue-play">계속재생</div>
+                            </div>
+                        </div>
+                    </div>`;
+
+        return iwContent;
     }
 }
 
@@ -1213,10 +1241,13 @@ class IntersectionCameraObj extends MarkerObj{
  * @param event 이벤트 종류 (click, close)
  */
 function infoWindowEvent(type, id, event) {
-    // _MapHandler[event](type, id);
-    const markerInfo = _MarkerHandle.findMarkerInfo(type);
+    const markerInfo = _MarkerHandle.findMarkerInfo(type); // 유형별 시설물 정보 찾기
+
+    // 시설물 마커들 중 id에 해당하는 객체 찾기
     const markers = markerInfo.markers;
     let idx = markers.findIndex(obj => obj.ID.toString() === id.toString());
+
+    // click, close 등 메서드로 등록한 것들도 키값으로 찾을 수 있음 obj.click() == obj['click']();
     markers[idx][event]();
 }
 
@@ -1279,32 +1310,6 @@ window.addEventListener('resize', function(event) {
 });
 
 
-/**
- * 시설물 이미지 유형 변경 이벤트
- * @param obj 시설물 객체
- * @param type 시설물 이미지 유형
- */
-function setMarkerImage(obj, type, isAtrd) {
-    const currentLevel = _Level;
-    let size = _size[currentLevel];
-    let point1 = size/2;
-    let point2 = size/2;
-    if (isAtrd) {
-        size = ( currentLevel >= 7 ) ? 24 : 48;
-        point1 = size/2;
-        point2 = size;
-    }
-
-    const imageSize = new kakao.maps.Size(size, size);
-    const imageSrc  = obj.imgSrc + type +'.png';
-    const imageOption = {
-        offset: new kakao.maps.Point(point1, point2),
-        alt: obj.NAME
-    };
-    const markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imageOption);
-    obj.marker.setImage(markerImage);
-}
-
 /**
  * 선택 리스트 스크롤 높이 반환 이벤트
  * @param selectIndex 선택 인덱스
@@ -1346,7 +1351,7 @@ function receiveMarkerData(jsonData, classType, type) {
     const title = $('.left-list-area .list-tab li.active > div:nth-child(2)').text();
     let emptyStr = "<div class='empty'>" + title + " 리스트가 없습니다.</div>";
     let mobileStr = "";
-    const markerInfo = _MarkerHandle.findMarkerInfo(type);
+    const {markers, isDraw, isDrawList} = _MarkerHandle.findMarkerInfo(type);
     if (jsonData && jsonData.length) {
         let markerArr = [];
         jsonData.forEach((obj)=>{
@@ -1354,27 +1359,25 @@ function receiveMarkerData(jsonData, classType, type) {
             markerObj.init();
             listStr += `<li id="${markerObj.type}-${markerObj.ID}" onclick="infoWindowEvent('${type}', '${markerObj.ID}' , 'click')">${markerObj.NAME}</li>`
             mobileStr += `<option value="${markerObj.ID}">${markerObj.NAME}</option>`;
-            markerInfo.markers.push(markerObj);
+            markers.push(markerObj);
             if (type ==='intersection') {
-                let detailArr = [];
                 markerObj.prop.detail.forEach((detail)=>{
                     const detailObj = new IntersectionCameraObj(detail);
                     detailObj.init();
-                    detailArr.push(detailObj);
                     _MarkerHandle.findMarkerInfo('intersectionCamera').markers.push(detailObj);
                 });
-                _MarkerHandle.setIsDraw('intersectionCamera', markerInfo.isDraw);
+                _MarkerHandle.setIsDraw('intersectionCamera', isDraw);
             }
             markerArr.push(markerObj);
         });
         _MarkerHandle.setMarkers(type, markerArr);
-        _MarkerHandle.showHideMarker(type, markerInfo.isDraw);
+        _MarkerHandle.showHideMarker(type, isDraw);
     }
     else {
         listStr = emptyStr;
     }
 
-    if (markerInfo.isDrawList) {
+    if (isDrawList) {
         const listSection  = $('.left-list-area .list-content.list');
         listSection.empty();
         listSection.html(listStr);
@@ -1389,67 +1392,6 @@ function receiveMarkerData(jsonData, classType, type) {
     }
 }
 
-/**
- * 시설물 데이터 처리 메서드
- * @param jsonData 수신 데이터
- * @param array 시설물 Object Array List
- * @param facilityClass 시설물 Object Class
- * @param listFlag 시설물 리스트 목록 표출 플래그
- * @param type 시설물 유형
- * @returns {*[]} 시설물 Object Array List
- */
-function receiveFacilityData(jsonData, facilityClass, type) {
-    if (_MapHandler[type].length > 0) {
-        _MapHandler[type].forEach((obj)=>{
-            if (obj.marker) {
-                obj.marker.setMap(null);
-            }
-            if (obj.polyline) {
-                obj.polyline.setMap(null);
-            }
-        });
-        _MapHandler[type] = [];
-    }
-    let listStr = "";
-    let mobileStr = "";
-    if (jsonData && jsonData.length > 0) {
-        jsonData.forEach((obj)=>{
-            const marker = new facilityClass(obj);
-            marker.init();
-            if (type === 'intersection') {
-                if (obj.detail && obj.detail.length > 0) {
-                    obj.detail.forEach((cameraObj)=>{
-                        const camera = new IntersectionCameraObj(cameraObj);
-                        camera.init();
-                        _MapHandler[type + 'Camera'].push(camera);
-                    })
-                }
-            }
-
-            listStr += `<li id="${type}-${marker.ID}" onclick="infoWindowEvent('${type}', '${marker.ID}' , 'click')">${marker.NAME}</li>`
-            mobileStr += `<option value="${marker.ID}">${marker.NAME}</option>`;
-            _MapHandler[type].push(marker);
-        });
-
-        if (_MapHandler[type + 'Flag']) {
-            _MapHandler.show(type);
-        }
-    }
-
-    if (_MapHandler[type + 'ListFlag'] === true) {
-        const listSection  = $('.left-list-area .list-content.list');
-        listSection.empty();
-        listSection.html(listStr);
-        const $mobileSelect = $('.mobile-select');
-        $mobileSelect.append($(mobileStr));
-        $mobileSelect.on('change', function(){
-            const id = $(this).val();
-            if (id && id !== "-") {
-                infoWindowEvent(type, id , 'click');
-            }
-        })
-    }
-}
 
 /**
  * 맵 중앙 아이콘 위 위치 좌표
@@ -1512,6 +1454,7 @@ function createVideoJs(id, url) {
         preload: "metadata",
     });
 
+    //에러발생 시 대체 이미지 생성
     video.on('error', ()=>{
         if (video.error().code === 4) {
             video.pause();
@@ -1553,8 +1496,6 @@ class MapHandler {
         const zoomControl = new kakao.maps.ZoomControl();
         this.map.addControl(zoomControl, kakao.maps.ControlPosition.RIGHT);
 
-        const handler = this;
-
         /**
          * Map Zoom Level Change 이벤트 (이미지 사이즈, 스마트 교차로 이미지 토글, 소통정보 정보 변경)
          */
@@ -1562,10 +1503,12 @@ class MapHandler {
             _Level = this.getLevel();
             const zoomChangeArray = ['cctv', 'vms', 'parking', 'incident', 'intersection', 'intersectionCamera'];
             zoomChangeArray.forEach((type)=>{
-                const markerInfo = _MarkerHandle.findMarkerInfo(type);
-                if (markerInfo.isDraw) {
-                    if (markerInfo.markers && markerInfo.markers.length > 0) {
-                        markerInfo.markers.forEach((obj)=>{
+                const isDraw = _MarkerHandle.isDraw(type);
+
+                if (isDraw) {
+                    const markers = _MarkerHandle.findMarkerArr(type);
+                    if (markers && markers.length > 0) {
+                        markers.forEach((obj)=>{
                             let imageType = "";
                             if (obj.imageType === '1') {
                                 imageType = obj.isClick ? '2' :'1';
@@ -1610,6 +1553,7 @@ class MapHandler {
         });
 
         /**
+         * 맵 드래그 이벤트
          * 좌표 데이터가의 양이 많으므로 이동 할때마다 영역별 소통정보를 새로 그려줌
          */
         kakao.maps.event.addListener(this.map, 'dragend', function() {
@@ -1618,6 +1562,47 @@ class MapHandler {
             }
         });
 
+        /**
+         * 맵 클릭 이벤트
+         */
+        kakao.maps.event.addListener(this.map, 'click', function (mouseEvent) {
+            // console.log(mouseEvent);
+        });
+    }
+
+    getLevel() {
+        return this.map.getLevel();
+    }
+
+    setLevel(level) {
+        if (!isNaN(level)) {
+            this.map.setLevel(level);
+        }
+        else {
+            console.error("Invalid Value Error - MapHandler.setValue(), Please Check The Zoom Level Value : ", level);
+        }
+    }
+
+    setCenter(position) {
+        if (position) {
+            this.map.setCenter(position);
+        }
+        else {
+            console.error("Invalid Values Error - MapHandler.setCenter, Value is Empty : ", position);
+        }
+    }
+
+    getBounds() {
+        return this.map.getBounds();
+    }
+
+    setBounds(bounds) {
+        if (bounds) {
+            this.map.setBounds(bounds);
+        }
+        else {
+            console.error("Invalid Values Error - MapHandler.setBound, Value is Empty : ", bounds);
+        }
     }
 
 }

+ 1 - 3
src/main/resources/templates/include/head.html

@@ -3,6 +3,4 @@
 <script th:src="@{/js/jquery/jquery-ui-touch-punch.min.js}"></script>
 <link rel="stylesheet" th:href="@{/css/common.css}">
 <link rel="stylesheet" th:href="@{/css/jquery-ui.css}">
-<!--<link rel="stylesheet" th:href="@{/js/jquery-confirm-v3.3.4/jquery-confirm.min.css}">-->
-<script th:src="@{/js/common/common.js}"></script>
-<!--<script th:src="@{/js/jquery-confirm-v3.3.4/jquery-confirm.min.js}"></script>-->
+<script th:src="@{/js/common/common.js}"></script>