Quellcode durchsuchen

update 2024-10-22

junggilpark vor 9 Monaten
Ursprung
Commit
220bb910e2

+ 1 - 1
conf/tsi-sig-server.pid

@@ -1 +1 @@
-7484
+2916

+ 2 - 18
src/main/resources/mybatis/mapper/main.xml

@@ -36,7 +36,7 @@
 						14:실패-서비스 제어 요청 실패,15:실패-서비스 가능 교차로가 존재하지 않음,16:자동종료-위치정보 수신 가능 시간 초과)	-->
 	<select id="getEvpServiceList" resultType="com.tsi.sig.server.vo.EvpServiceVo">
 		SELECT SERVICE_ID,
-			   CLCT_DT,
+			   DATE_FORMAT(clct_dt, '%Y-%m-%d %h:%i:%s') CLCT_DT,
 			   EV_NO,
 			   CUR_LAT,
 			   CUR_LNG,
@@ -49,22 +49,6 @@
 			   OCR_TYPE,
 			   SERVICE_DIST,
 			   STATUS_CD
--- 			   IF(STATUS_CD = 1,  '진행중',
--- 			   IF(STATUS_CD = 2,  '정상종료',
--- 			   IF(STATUS_CD = 3,  '취소-아직 통과하지 않은 교차로 존재',
--- 			   IF(STATUS_CD = 4,  '센터강제종료-운영자가 서비스를 강제 종료',
--- 			   IF(STATUS_CD = 5,  '비정상종료-서비스가 존재하지 않음',
--- 			   IF(STATUS_CD = 6,  '서비스 시작 실패',
--- 			   IF(STATUS_CD = 7,  '비정상정료-앱서버에 에러 발생',
--- 			   IF(STATUS_CD = 8,  '비정상종료-일정시간 앱에서 위치 및 속도 정보가 오지 않음',
--- 			   IF(STATUS_CD = 9,  '자동종료-경로이탈',
--- 			   IF(STATUS_CD = 10, '자동종료-경로진입 가능시간 초과',
--- 			   IF(STATUS_CD = 11, '자동종료-정차가능시간 초과',
--- 			   IF(STATUS_CD = 12, '취소',
--- 			   IF(STATUS_CD = 13, '실패-서비스 제어 요청',
--- 			   IF(STATUS_CD = 14, '실패-서비스 가능 교차로가 존재하지 않음',
--- 			   IF(STATUS_CD = 15, '자동종료', '-'
--- 			   ))))))))))))))) AS STATUS_DESC
 		FROM tb_evp_service
 		WHERE STATUS_CD = 1
 		ORDER BY CLCT_DT
@@ -72,7 +56,7 @@
 
 	<select id="getEvpHistoryList" parameterType="java.util.HashMap" resultType="com.tsi.sig.server.vo.EvpServiceVo">
 		SELECT SERVICE_ID,
-			   CLCT_DT,
+			   DATE_FORMAT(clct_dt, '%Y-%m-%d %h:%i:%s') CLCT_DT,
 			   EV_NO,
 			   CUR_LAT,
 			   CUR_LNG,

+ 163 - 9
src/main/resources/static/css/main.css

@@ -1170,18 +1170,113 @@ div.popState dl.jaywork dd strong.rblue {color:#607cd4; text-align:right;}
 
 .leftMenu .tabs {
     height: 30px;
-    border-bottom: 2px solid #3396ff;
+    border-bottom: 2px solid #595959;
     background-color: #000000;
 }
 
 .leftMenu .tabs li {
     float: left;
+    height: 100%;
+    padding: 0 10px;
+    border-right: 1px solid #595959;
+    color: #b2b2b2;
+    cursor: pointer;
+}
+.leftMenu .tabs li.on {
+    border-bottom: 1px solid #3396ff;
+}
+.leftMenu .tabs li > div img{
+    margin-bottom: 3px;
+}
+.leftMenu .tabs li > div {
+    display: flex;
+    gap: 5px;
+    align-items: center;
+    height: 100%;
+    font-weight: bold;
 }
-
 /* 트리리스트 */
 
 /* .leftMenu .iframeTreeList{width:95%;height:calc(100% - 45px);overflow:auto;padding:5px} */
-.leftMenu .historyBox,
+.leftMenu .historyBox {
+    width: 100%;
+    height: 175px;
+    border-bottom: 1px solid #595959;
+    background-color: #212121;
+    flex-direction: column;
+    display: none;
+    gap: 5px;
+}
+.leftMenu .evp-cur {
+    width: 100%;
+    height: 160px;
+    display: none;
+    background-color: #212121;
+    border-bottom: 1px solid #595959;
+}
+#evp-cur-list {
+    width: 100%;
+    height: calc(100% - 25px);
+    overflow: auto;
+}
+#evp-cur-list table {
+    width: 100%;
+    border-collapse: separate;
+    border-spacing: 0;
+}
+#evp-cur-list table thead{
+    position: sticky;
+    top: 0;
+    left: 0;
+}
+#evp-cur-list table tbody td {
+    font-size: 12px;
+    text-align: center;
+    color: #b2b2b2;
+    cursor: pointer;
+    height: 22px;
+    line-height: 22px;
+}
+#evp-cur-list table tbody tr:nth-child(even) td {
+    background-color: #3c3c3c;
+}
+#evp-cur-list table tbody tr:nth-child(odd) td {
+    background-color:#292828;
+}
+.leftMenu .title {
+    height: 25px;
+    background-color: #3c3c3c;
+    color: #b2b2b2;
+    display: flex;
+    align-items: center;
+    box-sizing: border-box;
+    padding-left: 10px;
+    border-bottom: 1px solid #595959;
+}
+.leftMenu .historyBox > div:nth-child(2) {
+    display: flex;
+    flex-direction: column;
+    /*align-items: center;*/
+    gap: 5px;
+    padding: 0 10px;
+}
+select#region {
+    width: 223px;
+    height: 29px;
+    box-sizing: border-box;
+    padding : 0 10px;
+}
+.leftMenu .historyBox > div > div > div:nth-child(1){
+    color: #b2b2b2;
+    width: 65px;
+    text-align: right;
+}
+
+.leftMenu .historyBox > div > div {
+    display: flex;
+    gap: 5px;
+    align-items: center;
+}
 .leftMenu .searchBox {
     width: 100%;
     height: 40px;
@@ -1193,10 +1288,6 @@ div.popState dl.jaywork dd strong.rblue {color:#607cd4; text-align:right;}
     background-color: black;
 }
 
-.leftMenu .historyBox {
-    display: none;
-}
-.leftMenu .historyBox .search-button,
 .leftMenu .searchBox .search-button {
     padding: 4px;
     border: 1px solid #eeeeee;
@@ -1228,17 +1319,61 @@ div.popState dl.jaywork dd strong.rblue {color:#607cd4; text-align:right;}
 
 .leftMenu #historyList {
     display: none;
-    height: calc(100% - 45px);
+    height: calc(100% - 407px);
     overflow: auto;
-    padding: 5px;
     background-color: #212121;
     box-sizing: border-box;
     width: 100%;
+    border-bottom: 1px solid #595959;
+}
+
+.leftMenu #evp-cur-list table thead th,
+.leftMenu #evp-cur-list table tbody,
+.leftMenu #evp-cur-list table tr td,
+.leftMenu #historyList table thead th,
+.leftMenu #historyList table tbody,
+.leftMenu #historyList table tr td{
+    border-bottom: 1px solid #595959;
+}
+
+.leftMenu #evp-cur-list table tbody tr.on td,
+.leftMenu #historyList table tbody tr.on td{
+    background-color: #3396FF;
+    color : #eeeeee;
 }
 
 .leftMenu #historyList table {
     width: 100%;
 }
+.leftMenu #historyList thead th,
+.leftMenu #evp-cur-list thead th {
+    background-color: #000000;
+    color: #b2b2b2;
+    line-height: 1.6;
+    height: 20px;
+}
+
+.leftMenu #evp-cur-list .empty-evp {
+    height: 112px;
+    background-color: #292828;
+    text-align: center;
+    color: #b2b2b2;
+    cursor: default;
+}
+.leftMenu #historyList .empty-history {
+    height: 449px;
+    background-color: #292828;
+    text-align: center;
+    color: #b2b2b2;
+    cursor: default;
+}
+
+.leftMenu #historyList thead th:not(:last-child),
+.leftMenu #evp-cur-list thead th:not(:last-child),
+.leftMenu #historyList tbody td:not(:last-child),
+.leftMenu #evp-cur-list tbody td:not(:last-child) {
+    border-right: 1px solid #595959;
+}
 
 .leftMenu .intSearchMenu {
     height: 70px;
@@ -3350,16 +3485,35 @@ cursor: pointer;border: 1px solid #ebebeb;border-bottom-color: #e2e2e2;border-ra
     /*transition: 0.2s ease-out;*/
 }
 
+#start_time, #end_time,
 #start, #end {
     width: 105px;
     height: 25px;
 }
+
+.history-btn {
+    padding: 4px;
+    border: 1px solid #eeeeee;
+    background-color: #3396ff;
+    color: white;
+    width: 50px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 5px;
+    font-weight: bold;
+    cursor: pointer;
+    margin-right: 20px;
+    margin-left: auto;
+}
 /*#map button, */
 #map > div:nth-child(7),
+select#region,
 /*#map > div:nth-child(8),*/
 #searchText,
 #start,
 #end,
+#start_time, #end_time,
 #map .mapToggle img,
 img[src="images/tab01_on.png"],
 img[src="images/tab01_off.png"],

BIN
src/main/resources/static/images/evp_icon.gif


BIN
src/main/resources/static/images/evp_icon.png


BIN
src/main/resources/static/images/evp_icon2.jpg


BIN
src/main/resources/static/images/int_icon.png


+ 108 - 55
src/main/resources/static/js/map.js

@@ -42,7 +42,8 @@ stateMap.set(2, '#FFFF00');
 stateMap.set(3, '#808080');
 stateMap.set(4, '#CC6600');
 stateMap.set(5, '#9933FF');
-
+var _isClick = null;
+let _evpData = [];
 
 $(document).ready(function () {
     init();
@@ -99,11 +100,69 @@ function init() {
     //getSignalInfo();
     const worker = new Worker('/js/worker.js');
     worker.postMessage({message:"worker START"});
+
     worker.onmessage = (ev)=>{
         const data = JSON.parse(ev.data);
-        drawEmergencyRoad(data);
+        const iframe = $('#iframeTreeList').contents();
+        const table = iframe.find('.evp-table');
+        const img = iframe.find('#tab2 img');
+        const imgName = '/images/evp_icon';
+        let exp = '.png';
+        let str = '<tr><td colspan="3" class="empty-evp">조회된 내용이 없습니다.</td></tr>';
+        _evpData = data;
+        if (data && data.length > 0) {
+            table.empty();
+            exp = '.gif';
+            str = '';
+            for (let obj of data) {
+                let className = '';
+                if (_isClick && obj.service_id === _isClick) {
+                    className = 'on';
+                }
+                str += `<tr class="tr_${obj.service_id} ${className}"><td>${obj.clct_dt}</td><td>${obj.service_id}</td><td>${obj.service_nm}</td></tr>`;
+            }
+
+            if (_isClick) {
+                drawEvp(_isClick);
+            }
+
+            table.html(str);
+            data.forEach((obj)=>{
+                iframe.find('.tr_' + obj.service_id).off('click');
+                iframe.find('.tr_' + obj.service_id).on('click',()=> drawEvp(obj.service_id));
+            })
+        }
+        else {
+            if (iframe.find('.empty-evp').length === 0) {
+                table.html(str);
+            }
+
+            if (_EmergencyMap.size){
+                _EmergencyMap.forEach((obj)=>{
+                    obj.clear();
+                });
+
+                _EmergencyMap.clear();
+                _isClick = null;
+            }
+        }
+        if (img.attr('src') !== imgName + exp) {
+            img.attr('src',imgName + exp);
+        }
+
     }
 
+    function drawEvp(serviceId) {
+       if (serviceId) {
+           const iframe = $('#iframeTreeList').contents();
+           if (!iframe.find('.tr_'+ serviceId + '.on').length) {
+               iframe.find('tr.on').removeClass('on');
+               iframe.find('.tr_'+ serviceId).addClass('on');
+           }
+           let idx = _evpData.findIndex((obj)=> obj.service_id === serviceId);
+           drawEmergencyRoad(_evpData[idx]);
+        }
+    }
 }
 
 let coordMarker;
@@ -303,73 +362,61 @@ function setEmergencyCurr(car, sigMap, road, arrive, dataMap) {
 }
 
 function drawEmergencyRoad(data) {
-    if (data && data.length) {
-        data.forEach((obj)=>{
-            const beforeObj = _EmergencyMap.get(obj.service_id);
-            if (!beforeObj) {
-                const emgObj = new EmergencyObj(obj);
-                if (_EmergencyMap.size === 0) {
-                    emgObj.setBound();
-                }
-
-                _EmergencyMap.set(obj.service_id, emgObj);
-            }
-            else {
-                beforeObj.car.moveMarker(getKakaoPosition(obj.event_list[0].cur_lat, obj.event_list[0].cur_lng));
-                obj.phase_list.forEach((sigObj)=>{
-                    const beforeSig = beforeObj.sig.get(sigObj.service_id + '_' + sigObj.seq_no);
-                    if (beforeSig) {
-                        const {a_head_lat, a_head_lng, a_mid_lat, a_mid_lng, a_end_lat, a_end_lng,
-                            b_head_lat, b_head_lng, b_mid_lat, b_mid_lng, b_end_lat, b_end_lng, state} = sigObj
-                        beforeSig.setState(state);
-                        if (beforeSig.a_ring) {
+    if (data) {
+        if (_EmergencyMap.size > 0) {
+            const evpObj = _EmergencyMap.get(data.service_id);
+            if (evpObj) {
+                evpObj.car.moveMarker(getKakaoPosition(data.event_list[0].cur_lat, data.event_list[0].cur_lng));
+                data.phase_list.forEach((obj)=>{
+                    const {a_head_lat, a_head_lng, a_mid_lat, a_mid_lng, a_end_lat, a_end_lng,
+                    b_head_lat, b_head_lng, b_mid_lat, b_mid_lng, b_end_lat, b_end_lng, state} = obj;
+                    const sig = evpObj.sig.get(obj.service_id + '_' + obj.seq_no);
+                    if (sig) {
+                        sig.setState(state);
+                        if (sig.a_ring) {
                             const a_head = getKakaoPosition(a_head_lat, a_head_lng);
                             const a_mid = getKakaoPosition(a_mid_lat, a_mid_lng);
                             const a_end = getKakaoPosition(a_end_lat, a_end_lng);
-                            beforeSig.a_ring.setPath([a_head, a_mid, a_end]);
+                            sig.a_ring.setPath([a_head, a_mid, a_end]);
                         }
 
-                        if (beforeSig.b_ring) {
+                        if (sig.b_ring) {
                             const b_head = getKakaoPosition(b_head_lat, b_head_lng);
                             const b_mid = getKakaoPosition(b_mid_lat, b_mid_lng);
                             const b_end = getKakaoPosition(b_end_lat, b_end_lng);
-                            beforeSig.b_ring.setPath([b_head, b_mid, b_end]);
+                            sig.b_ring.setPath([b_head, b_mid, b_end]);
                         }
-
-                        if (beforeSig.a_ring === null && beforeSig.b_ring === null) {
-                            beforeSig.createRing(sigObj);
+                        if (sig.a_ring === null && sig.b_ring === null) {
+                            sig.createRing(data);
                         }
                     }
+                    else {
+                        evpObj.sig.set(obj.service_id + '_' + obj.seq_no, new EmergencySig(obj));
+                    }
                 });
             }
-        });
-
-        if (_EmergencyMap.size !== data.length) {
-            const keyArr = Array.from(_EmergencyMap.keys());
-            for (let key of keyArr) {
-                let cnt = 0;
-                data.forEach((obj) => {
-                    if (obj.service_id === key) {
-                        cnt++;
-                    }
-                })
-                if (cnt === 0) {
-                    const sigObj = _EmergencyMap.get(key).sig;
-                    sigMap.delete(sigObj.lat + '_' + sigObj.lng);
-                    _EmergencyMap.get(key).clear();
-                    _EmergencyMap.delete(key);
-                }
+            else {
+                _EmergencyMap.forEach((obj)=>{
+                    obj.clear();
+                });
+                _EmergencyMap.clear();
+                const emgObj = new EmergencyObj(data);
+                _EmergencyMap.set(data.service_id, emgObj);
+                _isClick = data.service_id;
             }
         }
+        else {
+            const emgObj = new EmergencyObj(data);
+            _EmergencyMap.set(data.service_id, emgObj);
+            _isClick = data.service_id;
+        }
     }
     else {
-        if (_EmergencyMap.size > 0) {
-            _EmergencyMap.forEach((obj)=>{
-                obj.clear();
-            });
-            _EmergencyMap.clear();
-        }
-        // clearEmgMarker();
+        _EmergencyMap.forEach((obj)=>{
+            obj.clear();
+        });
+        _EmergencyMap.clear();
+        _isClick = null;
     }
 }
 
@@ -1589,6 +1636,7 @@ class EmergencyObj{
 
     init() {
         this.road = new EmergencyRoadObj(this.route_list);
+        this.road.setBound();
         if (this.phase_list && this.phase_list.length) {
             this.phase_list.forEach((obj)=>{
                 const sig = new EmergencySig(obj);
@@ -1604,10 +1652,11 @@ class EmergencyObj{
             this.road.hide();
         }
 
-        if (this.sig && this.sig.length) {
+        if (this.sig && this.sig.size) {
             this.sig.forEach((obj)=>{
                 obj.hide();
-            })
+            });
+            this.sig.clear();
         }
 
         if (this.car) {
@@ -1751,7 +1800,7 @@ class EmergencySig{
             stateColor = stateMap.get(Number(this.state));
         }
         const position = getKakaoPosition(this.lat, this.lng);
-        if (!sigMap.get(this.lat + '_' + this.lng)) {
+        if (!sigMap.get(this.service_id + '_' + this.sep_no)) {
             this.circle = new kakao.maps.Circle({
                 center : position,  // 원의 중심좌표 입니다
                 radius: 60, // 미터 단위의 원의 반지름입니다
@@ -1869,6 +1918,10 @@ class EmergencySig{
         if (this.b_ring) {
             this.b_ring.hide();
         }
+
+        if (sigMap && sigMap.size) {
+            sigMap.clear();
+        }
     }
 
     setCenter() {

+ 87 - 11
src/main/webapp/WEB-INF/jsp/treeListFrame.jsp

@@ -15,19 +15,55 @@
 <body class="sang" style="min-width:305px !important;overflow:hidden">
 <div class="leftMenu">
     <ul class="tabs">
-        <li><a href="javascript:goIntMenu()" class="tab" id="tab1"><img src="images/tab01_on.png" alt="교차로메뉴"/></a></li>
-        <li><a href="javascript:goEvpMenu()" class="tab" id="tab2"><img src="images/tab02_off.png" alt="긴급차량우선신호메뉴"/></a></li>
-        <div style="position: absolute; left: 95px; top: 5px; display: none;"><img src="images/map/btn_alert_A.gif" style="width: 22px"></div>
+        <li class="on"><div onclick="goIntMenu()" id="tab1"><img src="/images/int_icon.png" width="17px">교차로</div></li>
+        <li><div onclick="goEvpMenu()" id="tab2"><img src="/images/evp_icon.png" width="17px">긴급차량우선신호</div></li>
+<%--        <li><a href="javascript:goIntMenu()" class="tab" id="tab1"><img src="images/tab01_on.png" alt="교차로메뉴"/></a></li>--%>
+<%--        <li><a href="javascript:goEvpMenu()" class="tab" id="tab2"><img src="images/tab02_off.png" alt="긴급차량우선신호메뉴"/></a></li>--%>
+<%--        <div style="position: absolute; left: 95px; top: 5px;"><img src="images/map/btn_alert_A.gif" style="width: 22px"></div>--%>
     </ul>
     <div id="onOffTree"></div>
     <div class="searchBox">
         <input type="text" id="searchText" placeholder="검색어를 입력해주세요" autocomplete="false" onkeyup="searchTreeData(event)">
         <div class="search-button" onclick="searchTreeData()">검색</div>
     </div>
+    <div class="evp-cur">
+        <div class="title">실시간 긴급차량우선신호 리스트</div>
+        <div id="evp-cur-list">
+            <table>
+                <thead>
+                    <tr>
+                        <th>발생시각</th>
+                        <th>서비스 ID</th>
+                        <th>서비스명</th>
+                    </tr>
+                </thead>
+                <tbody class="evp-table">
+                    <tr>
+                        <td colspan="3" class="empty-evp">조회된 내용이 없습니다.</td>
+                    </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
     <div class="historyBox">
-        <input type="date" id="start" autocomplete="false">
-        <input type="date" id="end" autocomplete="false">
-        <div class="search-button" onclick="searchHistoryData()">검색</div>
+        <div class="title">긴급차량우선신호 이력조회</div>
+        <div>
+            <div>
+                <div>지역</div>
+                <select id="region">
+                    <option value="all" selected>전체</option>
+                </select>
+            </div>
+            <div>
+                <div>검색시작일</div>
+                <input type="date" id="start" autocomplete="false"/><input type="time" id="start_time">
+            </div>
+            <div>
+                <div>검색종료일</div>
+                <input type="date" id="end" autocomplete="false" /><input type="time" id="end_time">
+            </div>
+        </div>
+        <div class="history-btn" onclick="searchHistoryData()">검색</div>
     </div>
     <div id="intTree"></div>
     <div id="historyList">
@@ -36,12 +72,17 @@
                 <tr>
                     <th>발생시각</th>
                     <th>서비스 ID</th>
+                    <th>서비스명</th>
                 </tr>
             </thead>
             <tbody class="history-table">
+                <tr>
+                    <td colspan="3" class="empty-history">조회된 내용이 없습니다.</td>
+                </tr>
             </tbody>
         </table>
     </div>
+    <div></div>
     <div class="treeLoading"><img src="/css/themes/classic/throbber.gif"/></div>
 </div>
 <script type="text/javascript" src="${contextRoot }/js/common/moment.js"></script>
@@ -71,6 +112,30 @@
     let _regionMap = new Map();
     var _searchText = "";
     let timeout = null;
+    const $start     = $('#start');
+    const $startTime = $('#start_time');
+    const $end       = $('#end');
+    const $endTime   = $('#end_time');
+
+    $start.val(getDateToStr(new Date()));
+    $end.val(getDateToStr(new Date()));
+
+    $startTime.val('00:00');
+    $endTime.val('23:59');
+
+    function getDateToStr(date){
+        const year = date.getFullYear();
+        let month = date.getMonth() + 1;
+        let day = date.getDate();
+        if (month < 10){
+            month = '0' + month;
+        }
+        if (day < 10) {
+            day = '0' + day;
+        }
+        return year.toString() + '-' + month.toString() + '-' + day.toString();
+    }
+
     function setAddrMap(data) {
 
         _regionMap.clear();
@@ -595,26 +660,37 @@
 
 
     function goIntMenu() {
-        $('#tab1 img').attr('src','images/tab01_on.png');
-        $('#tab2 img').attr('src','images/tab02_off.png');
-
+        $('.tabs > li').eq(0).addClass('on');
+        $('.tabs > li').eq(1).removeClass('on');
         // $('.treeLoading').hide();
         $('#historyList').hide();
         $('#intTree').show();
         $('.searchBox').css('display', 'flex');
         $('.historyBox').css('display', 'none');
+        $('.leftMenu .evp-cur').hide();
+        if (window.parent._EmergencyMap && window.parent._EmergencyMap.size) {
+            window.parent._EmergencyMap.forEach((obj)=> obj.clear());
+            window.parent._EmergencyMap.clear();
+            $('.evp-table tr.on').removeClass('on');
+            window.parent._isClick = null;
+        }
 
     }
 
     function goEvpMenu() {
-        $('#tab1 img').attr('src','images/tab01_off.png');
-        $('#tab2 img').attr('src','images/tab02_on.png');
+        $('.tabs > li').eq(1).addClass('on');
+        $('.tabs > li').eq(0).removeClass('on');
 
         // $('.treeLoading').show();
         $('#historyList').show();
         $('#intTree').hide();
         $('.searchBox').css('display', 'none');
         $('.historyBox').css('display', 'flex');
+        $('.leftMenu .evp-cur').show();
+    }
+
+    function searchHistoryData() {
+
     }
 </script>
 </body>