Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 자바
- 집합_SET
- oracle
- 추상메서드
- exception
- 객체 비교
- Java
- 대덕인재개발원
- 예외미루기
- EnhancedFor
- 한국건설관리시스템
- 메소드오버로딩
- 생성자오버로드
- 오라클
- 참조형변수
- cursor문
- 다형성
- 자동차수리시스템
- 정수형타입
- 환경설정
- GRANT VIEW
- abstract
- 컬렉션프레임워크
- 제네릭
- 컬렉션 타입
- 인터페이스
- 어윈 사용법
- NestedFor
- 예외처리
- 사용자예외클래스생성
Archives
- Today
- Total
거니의 velog
(3) 랜딩 페이지 > 코드 리뷰 본문
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<c:set value="${pageContext.request.contextPath }" var="contextPath" />
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="author" content="부루마불" />
<meta name="description" content="대덕인재개발원 7월반 4조 부루마불의 여기갈래 프로젝트입니다." />
<meta name="keywords" content="부루마불, 여기갈래, 여행, 통합, 플랫폼" />
<meta name="copyright" content="대덕인재개발원" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>여기갈래 > 랜딩 페이지</title>
<!-- 사용자 페이지 > 헤더세팅 영역 -->
<tiles:insertAttribute name="headerSettings" />
<%-- <c:remove var="message" scope="page" />
<c:remove var="message" scope="session" />
<c:remove var="message" scope="request" />
<c:remove var="message" scope="application" /> --%>
<c:if test="${not empty message }">
<script type="text/javascript">
//alert("${message}");
$(function(){
// 성공시
<c:if test="${msgflag eq 'su'}">
Swal.fire({
title: "성공",
text: "${message}",
icon: "success"
});
</c:if>
// 실패시
<c:if test="${msgflag eq 'fa'}">
Swal.fire({
title: "실패",
text: "${message}",
icon: "error"
});
</c:if>
// 정보성 메시지
<c:if test="${msgflag eq 'in'}">
Swal.fire({
title: "안내",
text: "${message}",
icon: "info"
});
</c:if>
});
<c:remove var="message" scope="request" />
<c:remove var="message" scope="session" />
</script>
</c:if>
<!--
내부 CSS
- 내부 CSS는 외부 CSS의 스타일링을 건드리지 않기 위해서
개별적인 페이지에다 스타일을 적용할 때 종종 쓴다.
- 보통 프로토타이핑 테스트용이나, FE Leader의 판단에 따라 여기에
추가적인 스타일을 작성한다.
-->
<style>
.msub a {
color: #333;
}
</style>
</head>
<body class="scroll">
<!-- 사용자 페이지 > 헤더 영역 -->
<tiles:insertAttribute name="header" />
<!-- 사용자 페이지 > 랜딩 페이지 구현 영역 -->
<tiles:insertAttribute name="userMainContainer" />
<!-- 사용자 페이지 > 푸터 영역 -->
<tiles:insertAttribute name="footer" />
<!-- 사용자 페이지 > 자바스크립트 세팅 영역 -->
<tiles:insertAttribute name="settings" />
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- 랜딩페이지 css -->
<link href="${contextPath }/resources/css/index.css" rel="stylesheet" />
<!-- 메인 슬라이드 구역 -->
<section class="mainSlideContainer">
<div class="mainSlideTxt">
<h2>
<span>YoGi gAlE</span>
<br />
TRIP ROAD
</h2>
<p>
우리 지금, 떠나요!<br />
가장 쉽게! 가장 빠르게! 가장 즐겁게!<br />
대한민국의 중심으로 통하는 길
</p>
</div>
<article class="mainSlider">
<div>
<img src="${contextPath }/resources/images/slide1.jpg" alt="슬라이드 이미지" />
</div>
<div>
<img src="${contextPath }/resources/images/slide2.jpg" alt="슬라이드 이미지" />
</div>
<div>
<img src="${contextPath }/resources/images/slide3.jpg" alt="슬라이드 이미지" />
</div>
<div>
<img src="${contextPath }/resources/images/slide4.jpg" alt="슬라이드 이미지" />
</div>
<div>
<img src="${contextPath }/resources/images/slide5.jpg" alt="슬라이드 이미지" />
</div>
</article>
</section>
<!-- 여행 정보 구역 -->
<section class="journeyInfoContainer cen">
<h3>어디로 여행을 떠나시나요?</h3>
<div class="journeyInfoSearchContents">
<div>
<input type="text" class="form-control" id="jourInfoSearch" name="jourInfoSearch" placeholder="도시명으로 검색해보세요." />
<button type="button" id="searchBtn">
<i class="fas fa-search"></i>
</button>
</div>
</div>
<div class="journeyInfoContents">
<!-- 반복 시작 구간 -->
<c:choose>
<c:when test="${not empty journeyList8 }">
<c:forEach items="${journeyList8 }" var="journey">
<article>
<div class="infoThumbnailBox">
<img src="${journey.infoPreviewimg }" alt="여행 정보 썸네일 이미지" />
</div>
<div>
<h4 class="textDrop">${journey.infoEngname }</h4>
<span class="infoTitle textDrop">${journey.infoName }</span>
<p>
${journey.infoDescription }
</p>
<c:if test="${journey.infoFlightyn eq 'y' }">
<span class="airportText">
<span>
<c:if test="${journey.infoFlight eq 'str' }">
직항
</c:if>
<c:if test="${journey.infoFlight eq 'round' }">
왕복
</c:if>
</span>
<span>${journey.infoFlighttime }</span>
</span>
</c:if>
<c:if test="${journey.infoVisayn eq 'y' }">
<span class="visaText">
<span>
<c:if test="${journey.infoVisaexp eq 'visa' }">
비자
</c:if>
<c:if test="${journey.infoVisaexp eq 'none' }">
무비자
</c:if>
</span>
<span>${journey.infoVisatime }</span>
</span>
</c:if>
<span class="voltageTxt">
<span>콘센트</span>
<span>${journey.infoVoltage }</span>
</span>
<span class="infoTimediferTxt">
<span>한국대비</span>
<span>${journey.infoTimedifer }</span>
</span>
<input type="hidden" class="infoNo" name="infoNo" value="${journey.infoNo }" />
</div>
</article>
</c:forEach>
</c:when>
<c:otherwise>
<article style="text-align: center; width: 50%; margin: 0px auto; float: none; cursor: auto; background-color: #333; color: white; padding: 20px; border-radius: 4px;">
등록된 여행 정보가 없습니다.
</article>
</c:otherwise>
</c:choose>
</div>
</section>
<!-- 여행 정보 모달창 -->
<section class="infoModalContents">
<div class="infoModalBox cen">
<div class="infoModalClose">
<div></div>
<div></div>
</div>
<article class="infoModalLeft">
<div>
<div class="modalInfoSetting">
<span>여행 장소(영어)</span>
<h5>여행 장소</h5>
<p>여행 내용</p>
</div>
<div class="infoModalFourSection">
<div>
<div>
<i class="fas fa-plane"></i>
항공
</div>
<div>
<span>없음</span>
<span>-</span>
</div>
</div>
<div>
<div>
<i class="fas fa-passport"></i>
비자
</div>
<div>
<span>없음</span>
<span>-</span>
</div>
</div>
<div>
<div>
<i class="fas fa-plug"></i>
전압
</div>
<div>
<span>콘센트</span>
<span>220V</span>
</div>
</div>
<div>
<div>
<i class="fas fa-clock"></i>
시차
</div>
<div>
<span>한국대비</span>
<span>없음</span>
</div>
</div>
</div>
<a href="/myplan/makeplan.do" class="btn btn-info makePlanSty <c:if test="${empty sessionInfo }">noUserBlockModal</c:if>" style="color: white;">
일정만들기
<i class="fas fa-chevron-right"></i>
</a>
</div>
</article>
<article class="infoModalRight">
<div class="infoModalImgBox">
<img src="${contextPath }/resources/images/Jeju.jpg" alt="여행 정보 이미지" />
</div>
</article>
</div>
</section>
<!-- 플래너 이동 표출 영역 -->
<section class="plannerMoveContainer">
<div class="plannerContents">
<h4>여행을 떠나요</h4>
<p>
대한민국은 다양한 자연 경관과 역사적 명소로 가득한 아름다운 나라입니다.
<br />
전통 음식과 문화체험도 풍부하며, 한국의 아름다움과 다양성을 국내 여행으로 만나보세요.
</p>
<div>
<button type="button" class="btn btn-secondary plannerMoveBtn">플래너로 이동</button>
</div>
</div>
</section>
<!-- 사이트 그래프 표출 영역 -->
<section class="siteGraphContainer cen">
<h3>누가 어디로 여행을 떠날까요?</h3>
<div class="siteGraphContents">
<article class="siteGraph">
<h4>성별 사이트 이용자 수(%)</h4>
<canvas id="genderPieGraph"></canvas>
</article>
<article class="siteGraph">
<h4>주간 연령별 사이트 이용자 수</h4>
<canvas id="ageBarGraph"></canvas>
</article>
<article class="siteGraph">
<h4>여행지역 선호도(%)</h4>
<canvas id="areaPolarGraph"></canvas>
</article>
<article class="siteGraph">
<h4>주간 방문자 현황(명)</h4>
<canvas id="visitorStackGraph"></canvas>
</article>
</div>
</section>
<!-- 랜딩페이지 js -->
<script src="${contextPath }/resources/js/index.js"></script>
<!-- slick slide -->
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.css"/>
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js"></script>
<!-- chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
$(function(){
$.startHeaderStyle();
$.mainSlideSlickFn();
$(".mainSlider").mainSlideArrowStyle();
$(".slick-dots").mainSlideDotsStyle();
$.JourneyInfoModalFn();
$.startHeaderEmpty();
$.ajaxIndexJourneyInfoSearchFn();
$.makeplanClickEvent();
$(".plannerMoveBtn").click(function(){
location.href = "/myplan/planMain.do";
});
/* 종횡비 함수 */
$.eachJourneyInfoImgResizeFn();
var infoModalImgBox = $(".infoModalImgBox");
var infoModalImg = $(".infoModalImgBox img");
$.ratioBoxH(infoModalImgBox, infoModalImg);
/* chart.js */
/*
성별 사이트 이용자 수(%)
var genderPercent 에 담을 파라미터 값
param1 : 남자 성비(%)
param2 : 여자 성비(%)
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generateRandomGenderPercent() {
var malePercent = getRandomInt(10, 90); // 최소값을 10으로 설정
var femalePercent = 100 - malePercent;
return [malePercent, femalePercent];
}
var genderPercent = generateRandomGenderPercent();
console.log("성별 사이트 이용자 수(%):", genderPercent);
$.genderPieGraph(genderPercent);
/*
연령별 사이트 이용 현황(%)
var ageWeekUseSiteCnt 에 담을 파라미터 값
param1 : 주간 10대 이용 현황(명)
param2 : 주간 20대 이용 현황(명)
param3 : 주간 30대 이용 현황(명)
param4 : 주간 40대 이용 현황(명)
param5 : 주간 50대 이용 현황(명)
param6 : 주간 60대 이용 현황(명)
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generateRandomAgeWeekUseSiteCnt() {
var ageWeekUseSiteCnt = [];
// 주간 이용 현황을 랜덤으로 생성
for (var i = 1; i <= 6; i++) {
var randomValue = getRandomInt(100, 300); // 최소값을 100으로 설정
ageWeekUseSiteCnt.push(randomValue);
}
return ageWeekUseSiteCnt;
}
var ageWeekUseSiteCnt = generateRandomAgeWeekUseSiteCnt();
console.log("연령별 사이트 이용 현황(%):", ageWeekUseSiteCnt);
$.ageMixedGraph(ageWeekUseSiteCnt);
/*
여행지역 선호도(%)
var nineSectionPreference 에 담을 파라미터 값
param1 : 경기도 선호도(%)
param2 : 강원도 선호도(%)
param3 : 충청남도 선호도(%)
param4 : 충청북도 선호도(%)
param5 : 전라남도 선호도(%)
param6 : 전라북도 선호도(%)
param7 : 경상남도 선호도(%)
param8 : 경상북도 선호도(%)
param9 : 제주특별자치도 선호도(%)
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generateRandomPreferences() {
var preferences = [];
// 8개의 선호도를 랜덤으로 생성
for (var i = 1; i <= 8; i++) {
var randomValue = getRandomInt(10, 100); // 최소값을 10으로 설정
preferences.push(randomValue);
}
// 9번째 선호도를 설정
var sumOfPreferences = preferences.reduce((acc, val) => acc + val, 0);
preferences.push(Math.max(10, 100 - sumOfPreferences)); // 최소값을 10으로 설정
// 배열을 랜덤하게 섞기
preferences.sort(() => Math.random() - 0.5);
return preferences;
}
var nineSectionPreference = generateRandomPreferences();
console.log("여행지역 선호도(%):", nineSectionPreference);
$.areaPolarGraph(nineSectionPreference);
/*
주간 방문자 현황(명)
var weekVisiterAgeCnt 에 담을 파라미터 값
teen : 10대, 오늘 기준으로 일주일치 방문자 수
twenties : 20대, 오늘 기준으로 일주일치 방문자 수
thirties : 30대, 오늘 기준으로 일주일치 방문자 수
forties : 40대, 오늘 기준으로 일주일치 방문자 수
fifties : 50대, 오늘 기준으로 일주일치 방문자 수
sixties : 60대, 오늘 기준으로 일주일치 방문자 수
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function randomizeWeekVisiterAgeCnt() {
var randomizedWeekVisiterAgeCnt = {};
// 각 연령별 배열을 랜덤하게 생성
randomizedWeekVisiterAgeCnt.teen = Array.from({ length: 7 }, () => getRandomInt(10, 30));
randomizedWeekVisiterAgeCnt.twenties = Array.from({ length: 7 }, () => getRandomInt(10, 30));
randomizedWeekVisiterAgeCnt.thirties = Array.from({ length: 7 }, () => getRandomInt(10, 30));
randomizedWeekVisiterAgeCnt.forties = Array.from({ length: 7 }, () => getRandomInt(10, 30));
randomizedWeekVisiterAgeCnt.fifties = Array.from({ length: 7 }, () => getRandomInt(10, 30));
randomizedWeekVisiterAgeCnt.sixties = Array.from({ length: 7 }, () => getRandomInt(10, 30));
return randomizedWeekVisiterAgeCnt;
}
var randomizedWeekVisiterAgeCnt = randomizeWeekVisiterAgeCnt();
console.log("랜덤으로 배치된 주간 방문자 현황(명):", randomizedWeekVisiterAgeCnt);
$.visitorStackGraph(randomizedWeekVisiterAgeCnt);
});
</script>
@import url('https://fonts.cdnfonts.com/css/spongition');
/* 랜딩 페이지 스타일링 */
.mainSlideContainer {
position: relative;
}
.mainSlideTxt {
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 40;
color: white;
left: 200px;
}
.mainSlideTxt h2 {
font-family: 'Spongition', sans-serif;
font-weight: 800;
font-size: 5rem;
}
.mainSlideTxt p {
font-size: 1.9rem;
}
.mainSlideTxt h2 span {
color: yellow;
}
/* 슬라이드 스타일 */
.mainSlideContainer .mainSlider {
position: relative;
}
.mainSlider img {
width: 100%;
}
.mainSlider .slick-dots {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 15px;
list-style: none;
margin-bottom: 0px;
padding-left: 0px;
overflow: auto;
}
.mainSlider .slick-dots li {
float: left;
}
.mainSlider .slick-dots button {
display: block;
border-radius: 50%;
background-color: transparent;
border: none;
color: white;
font-size: 1.1rem;
text-align: center;
margin: 0px 5px;
}
.mainSlider .slick-active button {
color: black;
}
.mainSlider .slick-active i {
opacity: 0.6;
}
.mainSlider .slick-prev,
.mainSlider .slick-next {
position: absolute;
top: 55%;
transform: translateY(-50%);
z-index: 50;
background-color: rgba(0,0,0,0.6);
border: none;
outline: none;
padding: 20px 10px;
text-align: center;
border-radius: 4px;
color: white;
font-size: 2rem;
transition: all 0.4s;
}
.mainSlider .slick-prev:hover,
.mainSlider .slick-next:hover {
background-color: white;
color: black;
}
.mainSlider .slick-prev {
left: 15px;
}
.mainSlider .slick-next {
right: 15px;
}
/* 여행 정보 스타일 */
.journeyInfoContainer {
position: relative;
padding: 50px 0px;
}
.journeyInfoContainer h3 {
text-align: center;
font-size: 1.5rem;
font-weight: 700;
padding: 20px 0px;
margin-bottom: 0px;
}
.journeyInfoSearchContents>div {
overflow: auto;
position: relative;
width: 600px;
margin: 0px auto;
}
.journeyInfoSearchContents {
padding: 30px 0px;
}
.journeyInfoSearchContents input,
.journeyInfoSearchContents button {
float: left;
}
.journeyInfoSearchContents input {
width: 100%;
}
.journeyInfoSearchContents input::placeholder {
color: #dee2e6;
}
.journeyInfoSearchContents button {
display: block;
width: 20px;
height: 100%;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 10px;
border: none;
background-color: transparent;
color: #dee2e6;
transition: all 0.4s;
}
.journeyInfoSearchContents button:hover {
color: black;
}
.journeyInfoContents {
height: 840px;
margin: 25px 0px;
}
.journeyInfoContents article {
float: left;
width: calc(100% / 4 - 30px);
margin-right: 40px;
cursor: pointer;
transition: all 0.4s;
}
.journeyInfoContents article:hover {
transform: scale(1.03);
}
.journeyInfoContents article:nth-of-type(4),
.journeyInfoContents article:last-of-type {
margin-right: 0px;
}
.journeyInfoContents .infoThumbnailBox {
position: relative;
overflow: hidden;
height: 320px;
border-radius: 10px;
}
.journeyInfoContents .infoThumbnailBox img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.journeyInfoContents h4 {
margin-bottom: 5px;
}
.journeyInfoContents article>div:last-of-type {
padding: 20px 0px;
}
.journeyInfoContents article>div:last-of-type span {
display: block;
font-weight: 300;
}
.journeyInfoContents article p,
.journeyInfoContents article .airportText,
.journeyInfoContents article .visaText,
.journeyInfoContents article .voltageTxt,
.journeyInfoContents article .infoTimediferTxt {
display: none!important;
}
/* 여행 정보 모달창 */
.infoModalContents {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0,0,0,0.3);
z-index: 70;
display: none;
}
.infoModalBox {
position: absolute;
top: 55%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 60px;
overflow: auto;
border-radius: 10px;
}
.infoModalClose {
width: 30px;
height: 30px;
position: absolute;
top: 20px;
right: 20px;
cursor: pointer;
background-color: rgba(0,0,0,0.4);
border-radius: 4px;
}
.infoModalClose div {
width: 25px;
height: 1px;
background-color: white;
position: absolute;
top: 50%;
left: 50%;
}
.infoModalClose div:first-of-type {
transform: translate(-50%, -50%) rotate(45deg);
}
.infoModalClose div:last-of-type {
transform: translate(-50%, -50%) rotate(-45deg);
}
.infoModalBox article {
float: left;
width: calc(100% / 2);
padding: 24px;
}
.infoModalLeft>div {
height: 400px;
position: relative;
}
.modalInfoSetting span {
color: #AAB1B8;
font-size: 20px;
font-weight: 300;
}
.modalInfoSetting h5 {
font-size: 36px;
font-weight: 700;
margin-bottom: 20px;
}
.modalInfoSetting p {
font-weight: 300;
font-size: 14px;
margin-bottom: 20px;
}
.infoModalImgBox {
position: relative;
overflow: hidden;
height: 400px;
}
.infoModalImgBox img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.infoModalFourSection {
overflow: auto;
}
.infoModalFourSection>div {
float: left;
width: calc(100% / 4);
}
.infoModalFourSection>div>div:first-of-type {
margin-bottom: 10px;
}
.infoModalFourSection>div>div:last-of-type span {
display: block;
margin-bottom: 10px;
}
.infoModalFourSection>div>div:last-of-type span:first-of-type {
color: #AAB1B8;
font-size: 12px;
}
.infoModalFourSection>div>div:last-of-type span:last-of-type {
color: #737E8A;
font-size: 14px;
}
.makePlanSty {
display: block;
position: absolute;
bottom: 0;
padding: 8px 30px;
}
.makePlanSty i {
margin-left: 10px;
}
.noUserBlockModal::before {
content: "";
display: block;
width: 100%;
height: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0,0,0,0.6);
}
.noUserBlockModal::after {
content: "회원전용";
display: block;
width: 80px;
height: 20px;
background-color: #0dcaf0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 4px;
font-size: 0.8rem;
}
/* 그래프 디자인 영역 */
.siteGraphContainer {
position: relative;
padding-bottom: 100px;
}
.siteGraphContainer h3 {
text-align: center;
font-size: 1.5rem;
font-weight: 700;
padding: 20px 0px;
margin-bottom: 0px;
}
.siteGraphContents {
height: 800px;
}
.siteGraph {
float: left;
width: calc(100% / 2);
height: 400px;
padding: 40px 30px;
}
.siteGraph h4 {
font-size: 1.2rem;
}
/* 플래너 이동 표출 영역 */
.plannerMoveContainer {
height: 500px;
background-image: url(../images/plannerMoveBgImg.jpg);
background-repeat: no-repeat;
background-position: center;
background-size: cover;
background-attachment: fixed;
margin-bottom: 40px;
position: relative;
}
.plannerContents {
width: 400px;
height: 250px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: rgba(255, 255, 255, 0.6);
border-radius: 4px;
padding: 30px;
}
.plannerContents h4 {
font-size: 1.8rem;
font-weight: 500;
letter-spacing: 0px;
margin-bottom: 10px;
}
.plannerContents p {
font-size: 1.05rem;
font-weight: 300;
letter-spacing: 0px;
margin-bottom: 10px;
}
.plannerContents>div {
text-align: right;
}
/* 미디어 쿼리 (PC용) */
@media all and (max-width: 1600px) {
.mainSlideTxt h2 {
font-size: 4rem;
}
.mainSlideTxt p {
font-size: 1.5rem;
}
}
@media all and (max-width: 1400px) {
.mainSlideTxt {
top: 60%;
left: 150px;
}
.mainSlideTxt h2 {
font-size: 3rem;
}
.mainSlideTxt p {
font-size: 1.2rem;
}
}
@media all and (max-width: 1300px) {
.mainSlideTxt h2 {
font-size: 2.5rem;
}
.mainSlideTxt p {
font-size: 1rem;
}
.journeyInfoContainer {
padding: 50px 20px;
}
}
@media all and (max-width: 1060px) {
.journeyInfoContents article {
width: calc(100% / 2 - 20px);
}
.journeyInfoContents {
height: 1680px;
margin: 0px;
}
.journeyInfoContents article:nth-of-type(2),
.journeyInfoContents article:nth-of-type(4),
.journeyInfoContents article:nth-of-type(6),
.journeyInfoContents article:last-of-type {
margin-right: 0px;
}
/* 모달창 스타일 */
.infoModalBox {
padding: 30px;
}
.infoModalBox article {
float: none;
width: 100%;
padding-top: 100px;
}
.infoModalBox article:first-of-type {
padding-top: 0px;
}
.infoModalLeft>div,
.infoModalImgBox {
height: 200px;
}
.makePlanSty {
bottom: 120px;
right: 0;
border: none;
}
}
@media all and (max-width: 900px) {
.mainSlideTxt {
left: 100px;
}
.mainSlideTxt h2 {
font-size: 2rem;
}
.mainSlideTxt p {
font-size: 0.8rem;
}
.mainSlider .slick-prev,
.mainSlider .slick-next {
top: 60%;
padding: 15px 7px;
font-size: 1.4rem;
}
.mainSlider .slick-dots button {
font-size: 0.9rem;
}
.siteGraphContents {
height: 1600px;
}
.siteGraph {
float: none;
width: 100%;
}
}
/* 미디어 쿼리 (태블릿용) */
@media all and (max-width: 760px) {
.mainSlideTxt h2,
.mainSlideTxt p {
display: none;
}
}
@media all and (max-width: 680px) {
.mainSlider .slick-prev,
.mainSlider .slick-next {
display: none;
}
.mainSlider .slick-dots {
display: none;
}
.journeyInfoContents {
margin: 0px;
}
.journeyInfoContents article {
width: 100%;
margin-right: 0px;
}
.journeyInfoContents article:nth-of-type(5),
.journeyInfoContents article:nth-of-type(6),
.journeyInfoContents article:nth-of-type(7),
.journeyInfoContents article:last-of-type {
display: none;
}
.journeyInfoSearchContents {
padding: 30px 0px;
}
.journeyInfoSearchContents>div {
width: auto;
}
.infoModalBox article {
padding-top: 150px;
}
.infoModalBox article:first-of-type {
padding-top: 0px;
}
.plannerContents {
width: 300px;
height: auto;
}
}
@media all and (max-width: 500px) {
.makePlanSty {
display: none;
}
.plannerContents {
width: 250px;
height: auto;
}
}
// 공통 함수
// 메인 슬라이드 > slick
// 일시 정지 속성 : slickPause
// 재생 속성 : slickPlay
$.mainSlideSlickFn = function () {
$(".mainSlider").slick({
dots: true,
infinite: true,
fade: true,
speed: 2000,
slidesToShow: 1,
autoplay: true,
autoplaySpeed: 2000
});
};
$.fn.mainSlideArrowStyle = function () {
var slickPrev = this.find(".slick-prev");
var slickNext = this.find(".slick-next");
slickPrev.html("<i class='fas fa-chevron-left'></i>");
slickNext.html("<i class='fas fa-chevron-right'></i>");
};
$.fn.mainSlideDotsStyle = function () {
var slickDots = this.find("[role=tab]");
slickDots.html("<i class='fas fa-circle'></i>");
};
// 여행 정보 모달창 기능
$.JourneyInfoModalFn = function () {
// 모달창 닫기
var infoModalClose = $(".infoModalClose");
var infoModalContents = $(".infoModalContents");
infoModalClose.click(function () {
infoModalContents.hide();
});
// 모달창 열기
var journeyInfoContents = $(".journeyInfoContents article");
var modalInfoSetting = $(".modalInfoSetting");
journeyInfoContents.click(function () {
var thisIs = $(this);
var infoImgSrc = thisIs.find("img").attr("src").trim();
var infoH4 = thisIs.find("h4").text().trim();
var infoSpan = thisIs.find(".infoTitle").text().trim();
var infoP = thisIs.find("p").text().trim();
modalInfoSetting.find("span").text(infoH4);
modalInfoSetting.find("h5").text(infoSpan);
modalInfoSetting.find("p").text(infoP);
var infoModalImgBox = $(".infoModalImgBox");
infoModalImgBox.find("img").attr("src", infoImgSrc);
var airportText = thisIs.find(".airportText").html();
var airportHtmlEl = $(".infoModalFourSection>div:first-of-type>div:last-of-type");
airportHtmlEl.html("");
var visaText = thisIs.find(".visaText").html();
var visaHtmlEl = $(".infoModalFourSection>div:nth-of-type(2)>div:last-of-type");
visaHtmlEl.html("");
var voltageTxt = thisIs.find(".voltageTxt").html();
var voltageHtmlEl = $(".infoModalFourSection>div:nth-of-type(3)>div:last-of-type");
voltageHtmlEl.html("");
var infoTimediferTxt = thisIs.find(".infoTimediferTxt").html();
var infoTimediferHtmlEl = $(".infoModalFourSection>div:last-of-type>div:last-of-type");
infoTimediferHtmlEl.html("");
var emptyHtmlEl = "<span>없음</span><span>-</span>";
if(airportText != undefined) {
airportHtmlEl.html(airportText);
}else {
airportHtmlEl.html(emptyHtmlEl);
}
if(visaText != undefined) {
visaHtmlEl.html(visaText);
}else {
visaHtmlEl.html(emptyHtmlEl);
}
if(voltageTxt != undefined) {
voltageHtmlEl.html(voltageTxt);
}else {
voltageHtmlEl.html(emptyHtmlEl);
}
if(infoTimediferTxt != undefined) {
infoTimediferHtmlEl.html(infoTimediferTxt);
}else {
infoTimediferHtmlEl.html(emptyHtmlEl);
}
var infoNoVal = thisIs.find(".infoNo").val();
$("#choiceInfoNo").val(infoNoVal);
infoModalContents.show();
var infoModalImgBox = $(".infoModalImgBox");
var infoModalImg = $(".infoModalImgBox img");
$.ratioBoxH(infoModalImgBox, infoModalImg);
});
};
// chart.js
$.genderPieGraph = function(genderPercent){
const ctx1 = document.querySelector("#genderPieGraph");
var pieChart = new Chart(ctx1, {
type: 'pie',
data: {
labels: ['남자', '여자'],
datasets: [
{
label: '성별 사이트 이용자 수(%)',
data: genderPercent,
borderWidth: 1
}
]
},
options: {
responsive: true, // Enable responsiveness
maintainAspectRatio: false, // Allow aspect ratio to be adjusted
scales: {
y: {
beginAtzero: true
}
}
}
});
};
// 파스텔톤 랜덤 색상 함수
function generateRandomPastelColor() {
const hue = Math.floor(Math.random() * 360);
const pastelColor = `hsl(${hue}, 70%, 80%)`;
return pastelColor;
}
// 주어진 주간 연령별 사이트 이용 고객 수 배열을 기반으로
// 각 연령대의 사이트 이용 비율을 계산하여 퍼센트 배열을 반환하는 함수
function calculatePercentage(ageWeekUseSiteCnt) {
// 주어진 배열의 총 합을 계산
const totalCustomers = ageWeekUseSiteCnt.reduce((total, count) => total + count, 0);
// 각 연령대의 사이트 이용 비율을 계산하여 퍼센트로 변환
const percentageValues = ageWeekUseSiteCnt.map(count => ((count / totalCustomers) * 100).toFixed(2));
return percentageValues;
}
$.ageMixedGraph = function(ageWeekUseSiteCnt){
var ageUseSitePercent = calculatePercentage(ageWeekUseSiteCnt);
console.log(ageUseSitePercent);
const ctx2 = document.querySelector("#ageBarGraph");
var mixedChart = new Chart(ctx2, {
data: {
labels: ['10대', '20대', '30대', '40대', '50대', '60대 이상'],
datasets: [
{
type: 'line',
label: '주간 연령별 사이트 이용 현황(%)',
data: ageUseSitePercent,
borderWidth: 1,
backgroundColor: 'rgba(255, 99, 132, 1)',
borderColor: 'rgba(255, 99, 132, 1)',
yAxisID: 'percentageYAxis'
},
{
type: 'bar',
label: '주간 연령별 사이트 이용 고객 수(명)',
data: ageWeekUseSiteCnt,
borderWidth: 1,
backgroundColor: Array.from({ length: 6 }, () => generateRandomPastelColor()),
yAxisID: 'countYAxis'
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
percentageYAxis: {
type: 'linear',
position: 'left',
title: {
display: true,
text: '사이트 이용 비율 (%)'
},
ticks: {
beginAtZero: true,
max: 100
}
},
countYAxis: {
type: 'linear',
position: 'right',
title: {
display: true,
text: '사이트 이용 고객 수(명)'
},
ticks: {
beginAtZero: true
}
}
}
}
});
};
$.areaPolarGraph = function(nineSectionPreference){
const ctx3 = document.querySelector("#areaPolarGraph");
var polarChart = new Chart(ctx3, {
type: 'polarArea',
data: {
// 9개 광역행정구역(도)
labels: ['경기도', '강원도', '충청남도', '충청북도', '전라남도', '전라북도', '경상남도', '경상북도', '제주특별자치도'],
datasets: [
{
label: '여행지역 선호도(%)',
data: nineSectionPreference,
borderWidth: 1
}
]
},
options: {
responsive: true, // Enable responsiveness
maintainAspectRatio: false, // Allow aspect ratio to be adjusted
scales: {
y: {
beginAtzero: true
},
r: {
pointLabels: {
display: true,
centerPointLabels: true,
font: {
size: 14
}
}
}
},
}
});
};
// 객체 비구조화 할당 : weekVisiterAgeCnt = {teen, twenties, thirties, forties, fifties, sixties};
$.visitorStackGraph = function({teen, twenties, thirties, forties, fifties, sixties}){
const ctx4 = document.querySelector("#visitorStackGraph");
const getLast7Days = () => {
const today = new Date();
const last7Days = Array.from({ length: 7 }, (_, i) => {
const day = new Date(today);
day.setDate(today.getDate() - i);
const formattedDate = day.toISOString().slice(2, 10); // Format as 'YY-MM-DD'
return formattedDate;
});
return last7Days.reverse();
};
const weekDays = getLast7Days();
console.log(weekDays);
var stackChart = new Chart(ctx4, {
type: 'bar',
data: {
labels: weekDays,
datasets: [
{
label: '10대(명)',
data: teen
},
{
label: '20대(명)',
data: twenties
},
{
label: '30대(명)',
data: thirties
},
{
label: '40대(명)',
data: forties
},
{
label: '50대(명)',
data: fifties
},
{
label: '60대 이상(명)',
data: sixties
},
]
},
options: {
responsive: true, // Enable responsiveness
maintainAspectRatio: false, // Allow aspect ratio to be adjusted
scales: {
x: {
stacked: true,
},
y: {
stacked: true
}
}
}
});
};
// CSS in JS 기법
// 원본 CSS 스타일을 건드리지 않고 특정 페이지에서만 스타일링을 변경해야 하는 경우 자주 사용하는 기법
var headerEl = $("header");
var logoTxt = $(".logoTxt");
var loginHello = $(".loginHello");
var mLnbBtnDiv = $(".mLnbBtn div");
var pclnbA = $(".pclnb .main>a");
var mlnbLogoTxt = $(".mlnb .logoTxt");
var mlnbLoginHello = $(".mlnb .loginHello");
var msubA = $(".msub a");
var gnbBtnGroupA = $(".gnbBtnGroup a");
var gnbBtnGroupI = $(".gnbBtnGroup i");
var mlnbGnbBtnGroupA = $(".mlnb .gnbBtnGroup a");
var mlnbGnbBtnGroupI = $(".mlnb .gnbBtnGroup i");
$.initHeaderStyle = function () {
headerEl.removeAttr("style");
logoTxt.removeAttr("style");
loginHello.removeAttr("style");
mLnbBtnDiv.removeAttr("style");
pclnbA.removeAttr("style");
mlnbLogoTxt.removeAttr("style");
mlnbLoginHello.removeAttr("style");
msubA.removeAttr("style");
gnbBtnGroupA.removeAttr("style");
gnbBtnGroupI.removeAttr("style");
mlnbGnbBtnGroupA.removeAttr("style");
mlnbGnbBtnGroupI.removeAttr("style");
};
$.startHeaderStyle = function () {
headerEl.css({
transition: "all 0.4s",
backgroundColor: "rgba(0,0,0,0.6)"
});
logoTxt.css({
color: "#eee"
});
mlnbLogoTxt.css({
color: "#333"
});
loginHello.css({
color: "#eee"
});
mlnbLoginHello.css({
color: "#333"
});
pclnbA.css({
color: "#eee"
});
mLnbBtnDiv.css({
backgroundColor: "#eee"
});
msubA.css({
color: "#333"
});
gnbBtnGroupA.css({
backgroundColor: "#eee"
});
gnbBtnGroupI.css({
color: "#333"
});
mlnbGnbBtnGroupA.css({
backgroundColor: "#333"
});
mlnbGnbBtnGroupI.css({
color: "#eee"
});
gnbBtnGroupA.mouseover(function () {
var thisIs = $(this);
thisIs.css({
backgroundColor: "#333"
});
thisIs.find("i").css({
color: "#eee"
});
});
gnbBtnGroupA.mouseout(function () {
var thisIs = $(this);
thisIs.css({
backgroundColor: "#eee"
});
thisIs.find("i").css({
color: "#333"
});
});
mlnbGnbBtnGroupA.mouseover(function () {
var thisIs = $(this);
thisIs.css({
backgroundColor: "#eee"
});
thisIs.find("i").css({
color: "#333"
});
});
mlnbGnbBtnGroupA.mouseout(function () {
var thisIs = $(this);
thisIs.css({
backgroundColor: "#333"
});
thisIs.find("i").css({
color: "#eee"
});
});
};
$.scrollHeaderStyle = function () {
headerEl.css({
backgroundColor: "white"
});
logoTxt.css({
color: "#333"
});
loginHello.css({
color: "#333"
});
pclnbA.css({
color: "#333"
});
mLnbBtnDiv.css({
backgroundColor: "#333"
});
gnbBtnGroupA.css({
backgroundColor: "black"
});
gnbBtnGroupI.css({
color: "white"
});
gnbBtnGroupA.mouseover(function () {
var thisIs = $(this);
thisIs.css({
backgroundColor: "#eee"
});
thisIs.find("i").css({
color: "#333"
});
});
gnbBtnGroupA.mouseout(function () {
var thisIs = $(this);
thisIs.css({
backgroundColor: "#333"
});
thisIs.find("i").css({
color: "#eee"
});
});
}
// 여행 정보 각각의 이미지 종횡비 변경 함수
$.eachJourneyInfoImgResizeFn = function(){
$(".journeyInfoContents article").each(function(i, v){
var thisIs = $(this);
var infoThumbnailBox = thisIs.find(".infoThumbnailBox");
var infoThumbnailImg = thisIs.find("img");
$.ratioBoxH(infoThumbnailBox, infoThumbnailImg);
});
};
$.startHeaderEmpty = function(){
var winW = $(this).outerWidth();
/* 가로길이 600px 이하일 때 헤더에 공백 주기 */
var mainSlideContainer = $(".mainSlideContainer");
if(winW < 600) {
mainSlideContainer.addClass("emptySpace");
}else {
mainSlideContainer.removeClass("emptySpace");
}
};
// 랜딩 페이지 > 여행 정보 실시간 검색 기능 함수
$.ajaxIndexJourneyInfoSearchFn = function(){
var jourInfoSearch = $("#jourInfoSearch");
jourInfoSearch.keyup(function(){
var thisIs = $(this);
var thisVal = thisIs.val();
console.log("thisVal : ", thisVal);
var languageType = detectLanguage(thisVal);
console.log("languageType : " + languageType);
var journeyVO = {};
if(languageType == "korean") {
journeyVO.infoName = thisVal;
journeyVO.infoEngname = "";
}else if(languageType == "english") {
journeyVO.infoName = "";
journeyVO.infoEngname = thisVal;
}else {
journeyVO.infoName = "";
journeyVO.infoEngname = "";
}
$.ajax({
type: "get",
url: "/index/ajaxSearch.do",
data: journeyVO,
dataType: "json",
success: function(res){
console.log("res : ", res);
var searchHtml = "";
if(res.length == 0) {
searchHtml += `
<article style="text-align: center; width: 50%; margin: 0px auto; float: none; cursor: auto; background-color: #333; color: white; padding: 20px; border-radius: 4px;">
검색된 여행 정보가 없습니다.
</article>
`;
}
for(var i=0; i<res.length; i++){
searchHtml += `
<article>
<div class="infoThumbnailBox">
<img src="${res[i].infoPreviewimg}" alt="여행 정보 썸네일 이미지" />
</div>
<div>
<h4 class="textDrop">${res[i].infoEngname}</h4>
<span class="infoTitle textDrop">${res[i].infoName}</span>
<p>${res[i].infoDescription}</p>
<span class="airportText">`;
if(res[i].infoFlightyn == 'y'){
searchHtml += `<span>`;
if(res[i].infoFlight == "str"){
searchHtml += `직항</span>`;
}else {
searchHtml += `왕복</span>`;
}
searchHtml += `<span>${res[i].infoFlighttime}</span>`;
}else {
searchHtml += `<span>없음</span>
<span>-</span>`;
}
searchHtml += `</span>
<span class="visaText">`;
if(res[i].infoVisayn == 'y'){
searchHtml += `<span>`;
if(res[i].infoVisaexp == "visa"){
searchHtml += `비자</span>`;
}else {
searchHtml += `무비자</span>`;
}
searchHtml += `<span>${res[i].infoVisatime}</span>`;
}else {
searchHtml += `<span>없음</span>
<span>-</span>`;
}
searchHtml += `</span>
<span class="voltageTxt">
<span>콘센트</span>
<span>${res[i].infoVoltage}</span>
</span>
<span class="infoTimediferTxt">
<span>한국대비</span>
<span>${res[i].infoTimedifer}</span>
</span>
<input type="hidden" class="infoNo" name="infoNo" value="${res[i].infoNo}" />
</div>
</article>
`;
}
var journeyInfoContents = $(".journeyInfoContents");
journeyInfoContents.html("");
journeyInfoContents.append(searchHtml);
$.JourneyInfoModalFn();
$.eachJourneyInfoImgResizeFn();
}
});
});
};
function detectLanguage(inputValue) {
// 정규표현식을 사용하여 문자열이 한글인지 영어인지 판별
var koreanRegex = /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/;
var englishRegex = /^[a-zA-Z]*$/;
if (koreanRegex.test(inputValue)) {
return "korean";
} else if (englishRegex.test(inputValue)) {
return "english";
} else {
return "etc";
}
}
$.makeplanClickEvent = function(){
var makePlanSty = $(".makePlanSty");
makePlanSty.click(function(event){
event.preventDefault();
var thisIs = $(this);
var hrefVal = thisIs.attr("href");
var spanVal = thisIs.parents(".infoModalLeft").find(".modalInfoSetting>span").text();
console.log("spanVal : " + spanVal);
hrefVal += "?infoName=" + spanVal;
console.log("hrefVal : " + hrefVal);
location.href = hrefVal;
});
};
// 윈도우 가로 길이 변경 이벤트
$(window).resize(function(){
var winW = $(this).outerWidth();
if(winW < 1060) {
$.eachJourneyInfoImgResizeFn();
}
if(winW < 680) {
$.eachJourneyInfoImgResizeFn();
}
$.startHeaderEmpty();
});
// 윈도우 스크롤 이벤트
$(window).scroll(function () {
var scrD = $(this).scrollTop();
console.log("현재 스크롤의 위치 : " + scrD + " px");
// 스크롤 위치가 0px이면 herder를 투명하게, 아니면 하얀색 배경
if (scrD == 0) {
$.initHeaderStyle();
$.startHeaderStyle();
} else {
$.scrollHeaderStyle();
}
});
package kr.or.ddit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import kr.or.ddit.indexsearch.service.IndexSearchService;
import kr.or.ddit.users.login.vo.MemberVO;
import kr.or.ddit.users.myplan.vo.JourneyinfoVO;
import kr.or.ddit.utils.ServiceResult;
import kr.or.ddit.vo.RealTimeSenderVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
public class HomeController {
@Inject
private IndexSearchService indexSearchService;
// 랜딩 페이지
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home() {
return "home";
}
// 랜딩 페이지 리다이렉트
@CrossOrigin(origins = "http://localhost")
@RequestMapping(value = "/index.do", method = RequestMethod.GET)
public String index(Model model) {
/** 자료 수집 및 정의 */
Map<String, Object> param = new HashMap<String, Object>();
/** 서비스 호출 */
// 여행 정보 리스트(최신 글 순, 8개) 가져오기
indexSearchService.informationList8(param);
/** 반환 자료 */
List<JourneyinfoVO> journeyList8 = (List<JourneyinfoVO>) param.get("journeyList8");
/** 자료 검증 */
log.info("journeyList8 => {}", journeyList8);
/** 자료 반환 */
model.addAttribute("journeyList8", journeyList8);
return "user/index";
}
// 개인정보처리방침 페이지
@CrossOrigin(origins = "http://localhost")
@RequestMapping(value = "/personalInfo.do", method = RequestMethod.GET)
public String personalInfo() {
return "user/personalInfo";
}
// 영상정보처리기기 운영관리 방침 페이지
@CrossOrigin(origins = "http://localhost")
@RequestMapping(value = "/imageInfo.do", method = RequestMethod.GET)
public String imageInfo() {
return "user/imageInfo";
}
// ajax > 실시간 멤버 아이디 전체 리스트 가져오기
@GetMapping("/membersIdGet.do")
@ResponseBody
public List<MemberVO> ajaxMembersId() {
return indexSearchService.ajaxMembersId();
}
// ajax > 실시간 알림 > 내역 저장
@PostMapping("/allMemberRtAlertSave.do")
@ResponseBody
public String ajaxRtAlert(RealTimeSenderVO realVO) {
log.info("realVO : {}", realVO);
/** 자료 수집 및 정의 */
Map<String, Object> param = new HashMap<String, Object>();
param.put("realVO", realVO);
/** 서비스 호출 */
indexSearchService.ajaxRtAlert(param);
/** 반환 자료 */
ServiceResult result = (ServiceResult) param.get("result");
String judge = "";
if(result.equals(ServiceResult.OK)) {
judge = "OK";
}else {
judge = "FAIL";
}
return judge;
}
// ajax > 실시간 알림 메시지를 전역으로 가져와 뿌리깅
@GetMapping("/rtAlertGetMsg.do")
@ResponseBody
public Map<String, Object> ajaxRtSenderGetMsgFn(
HttpSession session
) {
/** 자료 수집 및 정의 */
Map<String, Object> param = new HashMap<String, Object>();
Map<String, Object> resObj = new HashMap<String, Object>();
MemberVO memberVO = (MemberVO) session.getAttribute("sessionInfo");
if(memberVO != null) {
param.put("memId", memberVO.getMemId());
}
/** 서비스 호출 */
// 실시간 알림 메시지 가져오기
indexSearchService.ajaxRtSenderGetMsgFn(param);
/** 반환 자료 */
RealTimeSenderVO journeySender = (RealTimeSenderVO) param.get("journeySender");
int journeyCnt = (int) param.get("journeyCnt");
/** 자료 검증 */
log.info("journeySender : {}", journeySender);
log.info("journeyCnt : {}", journeyCnt);
/** 자료 반환 */
resObj.put("journeySender", journeySender);
resObj.put("journeyCnt", journeyCnt);
return resObj;
}
// ajax > 바로 가기 클릭 시 안 본 실시간 알림을 본 것으로 처리
@PostMapping("/readRtAlert.do")
@ResponseBody
public String rtAlertRead(@RequestBody String realrecNo) {
log.info("realrecNo : {}", realrecNo);
/** 자료 수집 및 정의 */
Map<String, Object> param = new HashMap<String, Object>();
param.put("realrecNo", realrecNo);
/** 서비스 호출 */
indexSearchService.ajaxRtAlertRead(param);
/** 반환 자료 */
ServiceResult result = (ServiceResult) param.get("result");
String judge = "";
if(result.equals(ServiceResult.OK)) {
judge = "OK";
}else {
judge = "FAIL";
}
return judge;
}
// ajax > 실시간 알림 > 동행 참가 요청 > 해당 플래너 찾기
@GetMapping("/planDetailCreateMemId.do")
@ResponseBody
public MemberVO planDetailCreateMemId(String plNo) {
log.info("plNo : {}", plNo);
return indexSearchService.planDetailCreateMemId(plNo);
}
// ajax > 로그인할 멤버 정보 가져오기
@GetMapping("/loginMemInfoRtAlertSaveInfo.do")
@ResponseBody
public MemberVO loginMemInfoRtAlertSaveInfo(
MemberVO loginMemVO
) {
log.info("loginMemVO : {}", loginMemVO);
return indexSearchService.loginMemInfoRtAlertSaveInfo(loginMemVO);
}
// ajax > 로그인 알림 1번 출력 이후 바로 삭제
@PostMapping("/ajaxLoginRtAlertRemove.do")
@ResponseBody
public String ajaxLoginRtAlertRemove(
HttpSession session
) {
/** 자료 수집 및 정의 */
Map<String, Object> param = new HashMap<String, Object>();
MemberVO memberVO = (MemberVO) session.getAttribute("sessionInfo");
if(memberVO != null) {
param.put("memId", memberVO.getMemId());
}
/** 서비스 호출 */
indexSearchService.ajaxLoginRtAlertRemove(param);
/** 반환 자료 */
ServiceResult result = (ServiceResult) param.get("result");
String judge = "";
if(result.equals(ServiceResult.OK)) {
judge = "OK";
}else {
judge = "FAIL";
}
return judge;
}
// ajax > 딸랑이 클릭하면 모두 읽음 처리
@GetMapping("/rtAlertClickInit.do")
@ResponseBody
public String rtAlertClickInit(String memId) {
log.info("memId : {}", memId);
/** 자료 수집 및 정의 */
Map<String, Object> param = new HashMap<String, Object>();
param.put("memId", memId);
/** 서비스 호출 */
indexSearchService.rtAlertClickInit(param);
/** 반환 자료 */
ServiceResult result = (ServiceResult) param.get("result");
String judge = "";
if(result.equals(ServiceResult.OK)) {
judge = "OK";
}else {
judge = "FAIL";
}
return judge;
}
}
package kr.or.ddit.indexsearch.vo;
import org.springframework.web.multipart.MultipartFile;
import lombok.Data;
@Data
public class JourneyinfoVO {
private int infoNo;
private String infoName;
private String infoEngname;
private String infoDescription;
private String infoFlightyn;
private String infoFlight;
private String infoFlighttime;
private String infoVisayn;
private String infoVisaexp;
private String infoVisatime;
private String infoVoltage;
private String infoTimedifer;
private String infoRegdate;
private MultipartFile imgFile;
private String infoPreviewimg;
}
package kr.or.ddit.indexsearch.service;
import java.util.List;
import java.util.Map;
import kr.or.ddit.indexsearch.vo.JourneyinfoVO;
import kr.or.ddit.users.login.vo.MemberVO;
public interface IndexSearchService {
public void informationList8(Map<String, Object> param);
public List<JourneyinfoVO> searchJourneyList8(JourneyinfoVO journeyVO);
public List<MemberVO> ajaxMembersId();
public void ajaxRtAlert(Map<String, Object> param);
public void ajaxRtSenderGetMsgFn(Map<String, Object> param);
public void ajaxRtAlertRead(Map<String, Object> param);
public MemberVO planDetailCreateMemId(String plNo);
public MemberVO loginMemInfoRtAlertSaveInfo(MemberVO loginMemVO);
public void ajaxLoginRtAlertRemove(Map<String, Object> param);
public void rtAlertClickInit(Map<String, Object> param);
}
package kr.or.ddit.indexsearch.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import kr.or.ddit.indexsearch.service.IndexSearchService;
import kr.or.ddit.indexsearch.vo.JourneyinfoVO;
import kr.or.ddit.mapper.IndexSearchMapper;
import kr.or.ddit.users.login.vo.MemberVO;
import kr.or.ddit.utils.ServiceResult;
import kr.or.ddit.vo.RealTimeSenderVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class IndexSearchServiceImpl implements IndexSearchService {
@Inject
private IndexSearchMapper indexSearchMapper;
@Override
public void informationList8(Map<String, Object> param) {
/** 파라미터 조회 */
/** 파라미터 정의 */
List<JourneyinfoVO> journeyList8 = new ArrayList<JourneyinfoVO>();
/** 메인로직 처리 */
journeyList8 = indexSearchMapper.informationList8();
/** 반환자료 저장 */
param.put("journeyList8", journeyList8);
}
@Override
public List<JourneyinfoVO> searchJourneyList8(JourneyinfoVO journeyVO) {
return indexSearchMapper.searchJourneyList8(journeyVO);
}
@Override
public List<MemberVO> ajaxMembersId() {
return indexSearchMapper.ajaxMembersId();
}
@Override
public void ajaxRtAlert(Map<String, Object> param) {
/** 파라미터 조회 */
RealTimeSenderVO realVO = (RealTimeSenderVO) param.get("realVO");
/** 파라미터 정의 */
ServiceResult result = null;
int status = 0;
String[] realrecIdArr = null;
/** 메인로직 처리 */
// ajax > 실시간 알림 > 로그인 내역 저장
// 1. 가져온 로그 데이터를 발신자 테이블에 1번만 insert 해보아요
status = indexSearchMapper.insertSender(realVO);
if(status > 0) { // 마더 값이 들어감
// 2. 수신자 테이블에 수신자 멤버 수 만큼 insert 해 보아요
realrecIdArr = realVO.getRealrecIdArr();
for(String recId : realrecIdArr) {
realVO.setRealrecId(recId);
indexSearchMapper.insertReceiver(realVO);
}
result = ServiceResult.OK;
}else { // 실패
result = ServiceResult.FAILED;
}
/** 반환자료 저장 */
param.put("result", result);
}
@Override
public void ajaxRtSenderGetMsgFn(Map<String, Object> param) {
/** 파라미터 조회 */
String memId = (String) param.get("memId");
/** 파라미터 정의 */
RealTimeSenderVO journeySender = new RealTimeSenderVO();
int journeyCnt = 0;
/** 메인로직 처리 */
// 실시간 알림 정보를 가져오기(로그인한 세션 기준)
journeySender = indexSearchMapper.sender(memId);
// 실시간 알림 정보 갯수 가져오기(로그인한 세션 기준)
journeyCnt = indexSearchMapper.senderCnt(memId);
/** 반환자료 저장 */
param.put("journeySender", journeySender);
param.put("journeyCnt", journeyCnt);
}
@Override
public void ajaxRtAlertRead(Map<String, Object> param) {
/** 파라미터 조회 */
int realrecNo = Integer.parseInt((String) param.get("realrecNo"));
log.info("ajaxRtAlertRead > realrecNo : {}", realrecNo);
/** 파라미터 정의 */
int status = 0;
ServiceResult result = null;
/** 메인로직 처리 */
// 바로 가기 클릭 시 안 본 실시간 알림을 본 것으로 처리해 보아요. 업데이트여요.
status = indexSearchMapper.ajaxRtAlertRead(realrecNo);
log.info("ajaxRtAlertRead > status : {}", status);
if(status > 0) {
result = ServiceResult.OK;
}else { // 실패
result = ServiceResult.FAILED;
}
/** 반환자료 저장 */
param.put("result", result);
}
@Override
public MemberVO planDetailCreateMemId(String plNo) {
int intPlNo = Integer.parseInt(plNo);
return indexSearchMapper.planDetailCreateMemId(intPlNo);
}
@Override
public MemberVO loginMemInfoRtAlertSaveInfo(MemberVO loginMemVO) {
return indexSearchMapper.loginMemInfoRtAlertSaveInfo(loginMemVO);
}
@Override
public void ajaxLoginRtAlertRemove(Map<String, Object> param) {
/** 파라미터 조회 */
String memId = (String) param.get("memId");
/** 파라미터 정의 */
Map<String, Object> paramMap = new HashMap<String, Object>();
ServiceResult result = null;
int cnt = 0;
RealTimeSenderVO rtSender = new RealTimeSenderVO();
int realsenNo = 0;
int status = 0;
int status2 = 0;
/** 메인로직 처리 */
// 0. 일단 로그인 쌓인게 몇 건인지 가져와 봐요
cnt = indexSearchMapper.removeRealSenNoCnt();
log.info("cnt : {}", cnt);
if(cnt > 0) { // 1건 이상 있다는 말이므로 cnt 만큼 반복문을 돌려서 삭제해요
for(int i = 0; i < cnt; i++) {
// 1. 로그인한 알림의 realsenNo 값을 가져와요
rtSender = indexSearchMapper.removeSelectRealSenNo(memId);
// 1-1. 예외 처리: removeSelectRealSenNo가 null을 반환하는 경우
if (rtSender == null) {
log.warn("removeSelectRealSenNo returned null. Handle this case accordingly.");
// 처리할 내용을 여기에 추가하세요.
// 예를 들어, 오류 응답을 클라이언트로 반환하거나 기본값으로 초기화할 수 있습니다.
realsenNo = 0; // 기본값으로 초기화 예시
}else {
realsenNo = rtSender.getRealsenNo();
}
log.info("realsenNo : {}", realsenNo);
// 2. 조회한 realsenNo 값으로 발신자 테이블을 삭제해요
status = indexSearchMapper.removeRealtimereceiverTbl(realsenNo);
log.info("status : {}", status);
if(status > 0) {
// 3. 조회한 realsenNo 값으로 수신자 테이블을 삭제해요
status2 = indexSearchMapper.removeRealtimesenderTbl(realsenNo);
log.info("status2 : {}", status2);
if(status2 > 0) {
result = ServiceResult.OK;
}else {
result = ServiceResult.FAILED;
}
}else { // 실패
result = ServiceResult.FAILED;
}
}
}else { // 돌릴게 없으므로 그냥 ok 사인을 던져요
result = ServiceResult.OK;
}
/** 반환자료 저장 */
param.put("result", result);
}
@Override
public void rtAlertClickInit(Map<String, Object> param) {
/** 파라미터 조회 */
String memId = (String) param.get("memId");
/** 파라미터 정의 */
ServiceResult result = null;
int status = 0;
/** 메인로직 처리 */
status = indexSearchMapper.rtAlertClickInit(memId);
if(status > 0) { // 실시간 알림 초기화 완료
result = ServiceResult.OK;
}else { // 실시간 알림 초기화 실패
result = ServiceResult.FAILED;
}
/** 반환자료 저장 */
param.put("result", result);
}
}
package kr.or.ddit.mapper;
import java.util.List;
import kr.or.ddit.indexsearch.vo.JourneyinfoVO;
import kr.or.ddit.users.login.vo.MemberVO;
import kr.or.ddit.vo.RealTimeSenderVO;
public interface IndexSearchMapper {
public List<JourneyinfoVO> informationList8();
public List<JourneyinfoVO> searchJourneyList8(JourneyinfoVO journeyVO);
public List<MemberVO> ajaxMembersId();
public int insertSender(RealTimeSenderVO realVO);
public void insertReceiver(RealTimeSenderVO rtAlertVO);
public RealTimeSenderVO sender(String memId);
public int senderCnt(String memId);
public int ajaxRtAlertRead(int intRealrecNo);
public MemberVO planDetailCreateMemId(int intPlNo);
public MemberVO loginMemInfoRtAlertSaveInfo(MemberVO loginMemVO);
public int removeRealSenNoCnt();
public RealTimeSenderVO removeSelectRealSenNo(String memId);
public int removeRealtimesenderTbl(int realsenNo);
public int removeRealtimereceiverTbl(int realsenNo);
public int rtAlertClickInit(String memId);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.IndexSearchMapper">
<select id="informationList8" resultType="indexsearchVO">
SELECT *
FROM (
SELECT
info_no,
info_name,
info_engname,
info_description,
info_flightyn,
info_flight,
info_flighttime,
info_visayn,
info_visaexp,
info_visatime,
info_voltage,
info_timedifer,
info_previewimg,
info_regdate
FROM
journeyinfo
ORDER BY info_no DESC
)
<![CDATA[
WHERE ROWNUM <= 8
]]>
</select>
<select id="searchJourneyList8" parameterType="indexsearchVO" resultType="indexsearchVO">
SELECT *
FROM (
SELECT *
FROM journeyinfo
WHERE info_name LIKE '%' || #{infoName} || '%'
AND UPPER(info_engname) LIKE UPPER('%' || #{infoEngname} || '%')
ORDER BY info_no desc
)
<![CDATA[
WHERE ROWNUM <= 8
]]>
</select>
<select id="ajaxMembersId" resultType="memberVO">
select mem_id
from members
</select>
<insert id="insertSender" parameterType="rtsenderVO">
<selectKey keyProperty="realsenNo" order="BEFORE" resultType="int">
SELECT
seq_realtimesender.nextval
FROM
dual
</selectKey>
INSERT INTO realtimesender (
realsen_no,
realsen_id,
realsen_name,
realsen_title,
realsen_content,
realsen_type,
realsen_url,
realsen_pfimg
) VALUES (
#{realsenNo},
#{realsenId},
#{realsenName},
#{realsenTitle},
#{realsenContent},
#{realsenType},
#{realsenUrl},
#{realsenPfimg}
)
</insert>
<insert id="insertReceiver" parameterType="rtsenderVO">
INSERT INTO realtimereceiver (
realrec_no,
realrec_id,
realsen_readyn,
realsen_no
) VALUES (
seq_realtimereceiver.nextval,
#{realrecId},
#{realsenReadyn},
#{realsenNo}
)
</insert>
<select id="sender" parameterType="String" resultType="rtsenderVO">
select *
from (
select a.*
, b.realrec_no
, b.realrec_id
, b.realsen_readyn
from realtimesender a
, realtimereceiver b
where 1=1
and a.realsen_no = b.realsen_no
and b.realsen_readyn = 'N'
and b.realrec_id = 'chantest1'
order by a.realsen_no desc
) a
where 1 = 1
and ROWNUM = 1
</select>
<select id="senderCnt" parameterType="String" resultType="int">
select count(*) as journeyCnt
from realtimesender a
, realtimereceiver b
where 1=1
and a.realsen_no = b.realsen_no
and b.realsen_readyn = 'N'
and b.realrec_id = #{realrecId}
</select>
<update id="ajaxRtAlertRead" parameterType="int">
UPDATE realtimereceiver
SET
realsen_readyn = 'Y'
WHERE
realrec_no = #{realrecNo}
</update>
<select id="planDetailCreateMemId" parameterType="int" resultType="memberVO">
select *
from planer
where 1=1
and pl_no = #{intPlNo}
</select>
<select id="loginMemInfoRtAlertSaveInfo" parameterType="memberVO" resultType="memberVO">
select *
from members
where 1=1
and mem_id = #{memId}
and mem_pw = #{memPw}
</select>
<select id="removeSelectRealSenNo" parameterType="String" resultType="rtsenderVO">
select *
from (
select realsen_no
from realtimesender
where 1=1
and realsen_id = #{memId}
and realsen_type = 'logininfo'
order by realsen_no desc
) a
where 1=1
and rownum = 1
</select>
<delete id="removeRealtimesenderTbl" parameterType="int">
DELETE FROM realtimesender
WHERE realsen_no = #{realsenNo}
</delete>
<delete id="removeRealtimereceiverTbl" parameterType="int">
DELETE FROM realtimereceiver
WHERE realsen_no = #{realsenNo}
</delete>
<select id="removeRealSenNoCnt" resultType="int">
select count(*) as cnt
from realtimesender
where 1=1
and realsen_type = 'logininfo'
</select>
<update id="rtAlertClickInit" parameterType="String">
UPDATE realtimereceiver b
SET b.realsen_readyn = 'Y'
WHERE EXISTS (
SELECT 1
FROM realtimesender a
WHERE a.realsen_no = b.realsen_no
AND b.realsen_readyn = 'N'
AND b.realrec_id = #{memId}
)
</update>
</mapper>
'대덕인재개발원 > 대덕인재개발원_최종 포트폴리오' 카테고리의 다른 글
(6) 로그인 페이지 > 화면 설명 (0) | 2024.02.15 |
---|---|
(5) 로그인 페이지 > 코드 리뷰 (0) | 2024.02.15 |
(4) 랜딩 페이지 > 화면 설명 (0) | 2024.02.15 |
(2) 프로젝트 구조 및 설정 2 (0) | 2024.02.15 |
(1) 프로젝트 구조 및 설정 1 (0) | 2024.02.15 |