Explorar o código

update 2024-10-10

junggilpark hai 9 meses
pai
achega
c16fd7190d

+ 10 - 0
src/main/java/com/its/web/controller/admin/AdminController.java

@@ -1,5 +1,6 @@
 package com.its.web.controller.admin;
 
+import com.its.web.service.common.CommonService;
 import com.its.web.service.notice.NoticeService;
 import com.its.web.service.popup.PopupService;
 import com.its.web.service.traffic.IntersectionService;
@@ -21,6 +22,9 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
 
 @Slf4j
 @RequiredArgsConstructor
@@ -32,6 +36,7 @@ public class AdminController {
     private final PopupService popupService;
     private final TrafficService trafficService;
     private final IntersectionService ixrService;
+    private final CommonService commonService;
 
     @ApiOperation(value = "00.공통 - 01.로그인")
     @GetMapping("")
@@ -98,6 +103,11 @@ public class AdminController {
     @GetMapping("/conn-statistics")
     public String adminConnStatistics(Model model) {
         model.addAttribute("selected", "statistics");
+        model.addAttribute("yearList", this.commonService.getYearList());
+        Date date = Calendar.getInstance().getTime();
+        SimpleDateFormat format = new SimpleDateFormat("MM");
+        String month = format.format(date);
+        model.addAttribute("month", Integer.parseInt(month));
         return "admin/conn-statistics";
     }
 

+ 6 - 0
src/main/java/com/its/web/controller/common/CommonController.java

@@ -2,6 +2,7 @@ package com.its.web.controller.common;
 
 import com.its.web.dto.common.ConnStatisticsDto;
 import com.its.web.dto.common.TbWwwOrgDto;
+import com.its.web.dto.common.YearDto;
 import com.its.web.service.common.CommonService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -32,6 +33,11 @@ public class CommonController {
     @ResponseBody
     public List<ConnStatisticsDto> getConnStatistics(@ModelAttribute ConnStatisticsDto.ConnStatisticsDtoReq req) {return this.service.getConnStatistics(req);}
 
+    @ApiOperation(value = "접속자 통계 년도 리스트(TB_WWW_CONN_HS)", response = YearDto.class, responseContainer = "ArrayList")
+    @PostMapping(value = "/year-list", produces = {"application/json; charset=utf-8"})
+    @ResponseBody
+    public List<YearDto> getYearList() {return this.service.getYearList();}
+
     @ApiOperation(value = "에디터 게시물 이미지 업로드")
     @PostMapping(value = "/image-upload")
     @ResponseBody

+ 18 - 0
src/main/java/com/its/web/dto/common/YearDto.java

@@ -0,0 +1,18 @@
+package com.its.web.dto.common;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel("YearDto(조회수 년도 정보)")
+public class YearDto {
+    @ApiModelProperty("년도")
+    @JsonProperty("rate")
+    private String rate;
+}

+ 3 - 0
src/main/java/com/its/web/mapper/its/common/CommonMapper.java

@@ -3,6 +3,7 @@ package com.its.web.mapper.its.common;
 import com.its.web.dto.common.CodeDto;
 import com.its.web.dto.common.ConnStatisticsDto;
 import com.its.web.dto.common.TbWwwOrgDto;
+import com.its.web.dto.common.YearDto;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.List;
@@ -23,4 +24,6 @@ public interface CommonMapper {
     List<ConnStatisticsDto> getConnWeekStatistics(Map<String, String> paramMap);
 
     List<ConnStatisticsDto> getConnYearStatistics(Map<String, String> paramMap);
+
+    List<YearDto> getYearList();
 }

+ 4 - 4
src/main/java/com/its/web/service/common/CommonService.java

@@ -3,6 +3,7 @@ package com.its.web.service.common;
 import com.its.web.dto.common.CodeDto;
 import com.its.web.dto.common.ConnStatisticsDto;
 import com.its.web.dto.common.TbWwwOrgDto;
+import com.its.web.dto.common.YearDto;
 import com.its.web.mapper.its.common.CommonMapper;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -13,10 +14,7 @@ import org.springframework.stereotype.Service;
 import javax.servlet.http.HttpServletRequest;
 import java.io.*;
 import java.net.URLDecoder;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
+import java.util.*;
 
 @Slf4j
 @RequiredArgsConstructor
@@ -157,4 +155,6 @@ public class CommonService {
         }
         return image;
     }
+
+    public List<YearDto> getYearList() { return this.mapper.getYearList(); }
 }

+ 37 - 21
src/main/resources/mybatis/mapper/its/common/CommonMapper.xml

@@ -52,30 +52,46 @@
     </select>
 
     <select id="getConnMonthStatistics" resultType="com.its.web.dto.common.ConnStatisticsDto" parameterType="java.util.HashMap">
-        SELECT
-            TO_CHAR(TO_DATE(A.MONTHS, 'YYYYMM'), 'YYYY-MM') AS conn_dt,
-            SUM(NVL(B.conn_cnt, 0)) AS conn_cnt
-        FROM ( SELECT #{toDate} AS MONTHS FROM DUAL
-               UNION ALL
-               SELECT TO_CHAR(ADD_MONTHS(TO_DATE(#{toDate}, 'YYYYMM'), -LEVEL), 'YYYYMM') MONTHS FROM DUAL
-               CONNECT BY LEVEL <![CDATA[<=]]> MONTHS_BETWEEN(TO_DATE(#{toDate}, 'YYYYMM'), TO_DATE(#{fromDate}, 'YYYYMM'))
-              ) A
-        LEFT OUTER JOIN TB_WWW_CONN_HS B ON A.MONTHS = SUBSTR(B.conn_day, 0, 6)
-        GROUP BY TO_CHAR(TO_DATE(A.MONTHS, 'YYYYMM'), 'YYYY-MM')
-        ORDER BY TO_CHAR(TO_DATE(A.MONTHS, 'YYYYMM'), 'YYYY-MM')
+        SELECT b.dt AS conn_dt
+             , NVL(SUM(a.conn_cnt), 0) conn_cnt
+          FROM ( SELECT SUBSTR(CONN_DAY, 0, 6) AS conn_dt
+                      , SUM(NVL(conn_cnt, 0)) AS conn_cnt
+                   FROM TB_WWW_CONN_HS
+                  WHERE TO_DATE(SUBSTR(CONN_DAY, 0, 6), 'YYYYMM')
+                BETWEEN TO_DATE(#{fromDate}, 'YYYYMM')
+                    AND TO_DATE(#{toDate}, 'YYYYMM')
+                  GROUP BY SUBSTR(CONN_DAY, 0, 6)
+                ) a
+              , ( SELECT TO_CHAR(ADD_MONTHS(TO_DATE(#{fromDate}, 'YYYYMM'), LEVEL - 1), 'YYYYMM') AS dt
+                    FROM dual
+                 CONNECT BY LEVEL <![CDATA[<=]]> MONTHS_BETWEEN(TO_DATE(#{toDate}, 'YYYYMM'), TO_DATE(#{fromDate}, 'YYYYMM')) + 1
+                ) b
+          WHERE b.dt = a.conn_dt(+)
+          GROUP BY b.dt
+          ORDER BY b.dt
     </select>
 
     <select id="getConnYearStatistics" resultType="com.its.web.dto.common.ConnStatisticsDto" parameterType="java.util.HashMap">
-        SELECT
-            A.YEARS AS conn_dt,
-            SUM(NVL(B.conn_cnt, 0)) AS conn_cnt
-            FROM ( SELECT (TO_NUMBER(#{fromDate}) - 1 + LEVEL) YEARS FROM DUAL
-            CONNECT BY LEVEL <![CDATA[<=]]> (TO_NUMBER(#{toDate}) + 1 - TO_NUMBER(#{fromDate}))
-            ) A
-        LEFT OUTER JOIN TB_WWW_CONN_HS B ON A.YEARS = SUBSTR(B.conn_day, 0, 4)
-        GROUP BY A.YEARS
-        ORDER BY A.YEARS
+        SELECT b.dt AS conn_dt
+             , NVL(SUM(a.conn_cnt), 0) conn_cnt
+        FROM ( SELECT SUBSTR(CONN_DAY, 0, 4) AS conn_dt
+                    , SUM(NVL(conn_cnt, 0)) AS conn_cnt
+               FROM TB_WWW_CONN_HS
+               WHERE TO_DATE(SUBSTR(CONN_DAY, 0, 4), 'YYYY')
+             BETWEEN TO_DATE(#{fromDate}, 'YYYY')
+                 AND TO_DATE(#{toDate}, 'YYYY')
+               GROUP BY SUBSTR(CONN_DAY, 0, 4)
+        ) a
+           , ( SELECT TO_CHAR(ADD_MONTHS(TO_DATE(#{fromDate}, 'YYYY'), ((LEVEL - 1) * 12) ), 'YYYY') AS dt
+               FROM dual
+                   CONNECT BY LEVEL <![CDATA[<=]]> MONTHS_BETWEEN(TO_DATE(#{toDate}, 'YYYY'), TO_DATE(#{fromDate}, 'YYYY')) / 12 + 1
+        ) b
+        WHERE b.dt = a.conn_dt(+)
+        GROUP BY b.dt
+        ORDER BY b.dt
     </select>
 
-
+    <select id="getYearList" resultType="com.its.web.dto.common.YearDto">
+        SELECT DISTINCT(SUBSTR(CONN_DAY, 0, 4)) RATE FROM TB_WWW_CONN_HS ORDER BY RATE ASC
+    </select>
 </mapper>

+ 21 - 0
src/main/resources/static/css/conn-statistics.css

@@ -137,6 +137,27 @@
     background: 0px 0px no-repeat rgb(255, 255, 255);
 }
 
+.wave,
+.date,
+._year,
+._month{
+    display: none;
+}
+.wave.on,
+.date.on,
+._year.on,
+._month.on{
+    display: block;
+}
+
+
+._year,
+._month,
+.type {
+    padding: 10px;
+    border: 1px solid rgb(204, 234, 234);
+}
+
 .title .button {
     display: inline-block;
     width: 100px;

+ 153 - 27
src/main/resources/templates/admin/conn-statistics.html

@@ -19,13 +19,32 @@
         <h2 class="admin-header">접속자 통계</h2>
         <div class="admin-content">
             <div class="title">
-                <select>
-                    <option value="dd" selected>일별</option>
-                    <option value="yy">최근 6개월</option>
-                    <option value="mn">월별</option>
-                    <option value="yy">년별</option>
+                <select name="type" title="구분" class="type">
+                    <option value="date" selected>일별</option>
+                    <option value="6">최근 6개월</option>
+                    <option value="_month">월별</option>
+                    <option value="_year">년별</option>
                 </select>
-                <input id="date" type="text" placeholder="날짜를 선택해주세요.">
+                <select name="year_from" title="연별 시작년" class="_year from_year">
+                    <option th:each="year : ${yearList}" th:unless="${year.rate} == ${#calendars.format(#calendars.createNow(), 'yyyy')}" th:value="${year.rate}" th:title="${year.rate + '년'}" th:text="${year.rate + '년'}"></option>
+                    <option th:each="year : ${yearList}" th:if="${year.rate} == ${#calendars.format(#calendars.createNow(), 'yyyy')}"
+                            th:value="${year.rate}" th:title="${year.rate + '년'}" th:text="${year.rate + '년'}" selected></option>
+                </select>
+                <select name="month" title="월별 시작월" class="_month from_month">
+                    <option th:each="num : ${#numbers.sequence(1, month)}" th:unless="${month} == ${num}" th:value="${num}" th:title="${num + '월'}" th:text="${num + '월'}"></option>
+                    <option th:each="num : ${#numbers.sequence(1, month)}" th:if="${month} == ${num}" selected th:value="${num}" th:title="${num + '월'}" th:text="${num + '월'}"></option>
+                </select>
+                <div class="wave">&nbsp;~&nbsp;</div>
+                <select name="year_to" title="연별 종료년" class="_year to_year">
+                    <option th:each="year : ${yearList}" th:unless="${year.rate} == ${#calendars.format(#calendars.createNow(), 'yyyy')}" th:value="${year.rate}" th:title="${year.rate + '년'}" th:text="${year.rate + '년'}"></option>
+                    <option th:each="year : ${yearList}" th:if="${year.rate} == ${#calendars.format(#calendars.createNow(), 'yyyy')}"
+                            th:value="${year.rate}" th:title="${year.rate + '년'}" th:text="${year.rate + '년'}" selected></option>
+                </select>
+                <select name="month" title="월별 종료월" class="_month to_month">
+                    <option th:each="num : ${#numbers.sequence(1, month)}" th:unless="${month} == ${num}" th:value="${num}" th:title="${num + '월'}" th:text="${num + '월'}"></option>
+                    <option th:each="num : ${#numbers.sequence(1, month)}" th:if="${month} == ${num}" selected th:value="${num}" th:title="${num + '월'}" th:text="${num + '월'}"></option>
+                </select>
+                <input id="date" class="date on" type="text" placeholder="날짜를 선택해주세요.">
                 <label for="date" style="display: none"></label>
                 <div th:class="button" onclick="searchStat()">조회</div>
                 <div th:class="excel-button" th:onclick="download()">
@@ -54,7 +73,10 @@
 </body>
 </html>
 
-<script>
+<script th:inline="javascript">
+
+    const yearList = [[${yearList}]];
+
     const $date = $('#date');
     const $list = $('.list-content');
     let startDate = new Date(new Date().setDate(new Date().getDate() - 9));
@@ -79,34 +101,65 @@
     });
 
     function getConnStatistics(fromDt, toDt) {
-        let period = Number(getDateDiff(toDt, fromDt));
+        const $type = $('.type');
+        const typeVal = $type.val()
+        const $fromYear = $('.from_year');
+        const $toYear = $('.to_year');
+        const $fromMonth = $('.from_month');
+        const $toMonth = $('.to_month');
         let type = "";
         let typeStr = "일";
-        let fromDate = dateFormatter(fromDt);
-        let toDate   = dateFormatter(toDt);
-        if (!isNaN(period)) {
-            if (period > 30) {
-                type = 'week';
-                typeStr = "주간";
-            }
-            if (period > 61) {
-                type = 'month';
-                typeStr = "월";
-                fromDate = fromDate.substring(0,6);
-                toDate = toDate.substring(0,6);
-            }
+        let fromDate = null;
+        let toDate = null;
+
+        if (typeVal === 'date' || typeVal === '6') {
+            let period = Number(getDateDiff(toDt, fromDt));
 
-            if (period > 365) {
-                type = 'year';
-                typeStr = "년도";
-                fromDate = fromDate.substring(0, 4);
-                toDate = toDate.substring(0, 4);
+            fromDate = dateFormatter(fromDt);
+            toDate = dateFormatter(toDt);
+            if (!isNaN(period)) {
+                if (period > 30) {
+                    type = 'week';
+                    typeStr = "주간";
+                }
+                if (period > 61) {
+                    type = 'month';
+                    typeStr = "월";
+                    fromDate = fromDate.substring(0, 6);
+                    toDate = toDate.substring(0, 6);
+                }
+
+                if (period > 365) {
+                    type = 'year';
+                    typeStr = "년도";
+                    fromDate = fromDate.substring(0, 4);
+                    toDate = toDate.substring(0, 4);
+                }
             }
         }
+        else if (typeVal === '_month') {
+            let from = $fromMonth.val();
+            let to = $toMonth.val();
+            if (from < 10) from = "0" + from;
+            if (to < 10) to = "0" + to;
+            type = 'month';
+            typeStr = "월";
+            fromDate = $fromYear.val() + from;
+            toDate = $toYear.val() + to;
+        }
+        else if (typeVal === '_year') {
+            type = 'year';
+            typeStr = "년도";
+            fromDate = $fromYear.val();
+            toDate = $toYear.val();
+        }
 
         startDate = fromDate;
         endDate = toDate;
 
+        if (fromDate > toDate) {
+            return alertError("검색 기간을 확인해주세요.", "접속자 통계 조회", null);
+        }
         const param = {
             fromDate : fromDate,
             toDate   : toDate,
@@ -130,7 +183,8 @@
             data.push(obj.conn_cnt);
             // $list.append($(`<div><div>${obj.conn_dt}</div><div>${obj.conn_cnt}</div></div>`))
             $list.append($(`<tr><td>${obj.conn_dt}</td><td>${obj.conn_cnt}</td></tr>`))
-        })
+        });
+
         Highcharts.chart('chart', {
             chart: {
                 type: 'column'
@@ -216,4 +270,76 @@
         link.remove();
     }
 
+    $('.type').on('change', function() {
+        const value = $(this).val();
+        const wave = $('.wave');
+        let arr = ['date', '_month', '_year'];
+        for (let className of arr) {
+            const el = $('.' + className);
+            if (el.hasClass('on')) {
+                el.removeClass('on');
+            }
+        }
+        wave.removeClass('on');
+
+        if (value === '6') {
+            const sixMonthAgo = new Date(new Date().setMonth(new Date().getMonth() - 5));
+            const beforeDate = getDateFormat(sixMonthAgo).substr(0, 8) + '01';
+            const afterDate = getDateFormat(new Date());
+            $date.data('daterangepicker').setStartDate(beforeDate);
+            $date.data('daterangepicker').setEndDate(afterDate);
+            $date.addClass('on');
+            $date.attr('readonly', true);
+        }
+        else {
+
+            const year = $('._year');
+
+            let dateVal;
+            switch (value) {
+                case 'date' :
+                    const start = getDateFormat(new Date(new Date().setDate(new Date().getDate() - 9)));
+                    const end = getDateFormat(new Date());
+                    $date.data('daterangepicker').setStartDate(start);
+                    $date.data('daterangepicker').setEndDate(end);
+                    $date.attr('readonly', false);
+                    //dateVal =  start + ' ~ ' + end;
+                    break;
+                case '_month' :
+                    year.addClass('on');
+                    wave.addClass('on');
+                    year.val(new Date().getFullYear());
+                    dateVal = new Date().getMonth() + 1;
+                    break;
+                case '_year' :
+                    dateVal = new Date().getFullYear();
+                    wave.addClass('on');
+                    break;
+            }
+
+            const selected = $('.' + value);
+            selected.addClass('on');
+            if (dateVal) {
+                selected.val(dateVal);
+            }
+        }
+    });
+
+    $('.year_from').on('change', function() {
+        if ($(this).val() === new Date().getFullYear()) {
+
+        }
+        else {
+
+        }
+    })
+
+    function getDateFormat(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 + '-' + month + '-' + day;
+    }
 </script>