merge master into develop - CscListRForm.jsp FAQ 아코디언 버그 수정

This commit is contained in:
jilee4unity
2026-05-28 23:34:06 +09:00
7250 changed files with 570509 additions and 25 deletions

View File

@@ -0,0 +1,269 @@
/**
* Discshar.js
*
* 할인 공유 기능을 관리하는 모듈
* 할인 슬라이더, 공유 링크 생성, 공유 결과 확인 등의 기능 제공
*/
const Discshar = (function() {
// 모듈 내부 변수 선언
let $slider; // 슬라이더 컨테이너 (ul 요소)
let $slides; // 슬라이드 아이템들 (li 요소들)
let slideWidth; // 각 슬라이드 너비 (마진 포함)
let currentSlide; // 현재 표시 중인 슬라이드 인덱스
let totalSlides; // 전체 슬라이드 개수 (복제 슬라이드 포함)
let slideInterval; // 자동 슬라이드 간격 (밀리초)
let autoSlideTimeout; // 자동 슬라이드 타이머 ID
/**
* 모듈 초기화 함수
* 슬라이더 초기화 및 이벤트 바인딩
*/
function init() {
initSlider(); // 슬라이더 요소 초기화
bindEvents(); // 이벤트 리스너 등록
}
/**
* 슬라이더 초기화 함수
* 슬라이더 요소 참조 가져오기, 크기 설정, 무한 루프를 위한 슬라이드 복제
*/
function initSlider() {
// 슬라이더 요소 참조 가져오기
$slider = $('.discountSlider ul');
$slides = $('.discountSlider li');
// 슬라이드 너비 계산 (요소 너비 + 마진)
slideWidth = $slides.outerWidth() + parseInt($slides.css('margin-right'));
// 초기 슬라이드 인덱스 및 총 개수 설정
currentSlide = 0;
totalSlides = $slides.length;
slideInterval = 3000; // 슬라이드 자동 전환 간격 (밀리초)
// 무한 루프 슬라이드를 위한 복제 요소 추가
// 첫 번째 슬라이드 앞에 마지막 슬라이드 복제본 추가
$slides.first().before($slides.last().clone());
// 마지막 슬라이드 뒤에 첫 번째 슬라이드 복제본 추가
$slides.last().after($slides.first().clone());
// 복제된 슬라이드를 포함하여 총 슬라이드 수 업데이트
totalSlides += 2;
// 모든 슬라이드를 포함할 수 있도록 컨테이너 너비 설정
$slider.width(totalSlides * slideWidth);
// 초기 위치를 첫 번째 실제 슬라이드로 설정 (복제 슬라이드 건너뛰기)
$slider.css('margin-left', -slideWidth);
// 자동 슬라이드 시작
startAutoSlide();
}
/**
* 이벤트 리스너 등록 함수
* 슬라이더 조작을 위한 다양한 이벤트 핸들러 연결
*/
function bindEvents() {
// 슬라이더에 마우스 이벤트 및 터치 이벤트 바인딩
$slider.on('mouseenter', stopAutoSlide) // 마우스 진입 시 자동 슬라이드 정지
.on('mouseleave', startAutoSlide) // 마우스 이탈 시 자동 슬라이드 재시작
.on('mousedown touchstart', startDrag) // 드래그 시작
.on('mousemove touchmove', drag) // 드래그 중
.on('mouseup touchend', endDrag); // 드래그 종료
// 문서 전체에 마우스업/터치엔드 이벤트 리스너 추가 (드래그 도중 슬라이더 밖으로 나갔을 때 대비)
$(document).on('mouseup touchend', endDrag);
// 이미지 기본 드래그 방지 (브라우저의 기본 동작 차단)
$('.discountSlider img').on('dragstart', function(event) { event.preventDefault(); });
}
/**
* 자동 슬라이드 시작 함수
* 일정 간격으로 다음 슬라이드로 자동 이동
*/
function startAutoSlide() {
autoSlideTimeout = setInterval(nextSlide, slideInterval);
}
/**
* 자동 슬라이드 정지 함수
* 자동 슬라이드 타이머 중지
*/
function stopAutoSlide() {
clearInterval(autoSlideTimeout);
}
/**
* 다음 슬라이드로 이동 함수
* 현재 슬라이드 인덱스 증가 후 슬라이드 이동
*/
function nextSlide() {
currentSlide++;
moveSlide();
}
/**
* 슬라이드 이동 함수
* 현재 슬라이드 인덱스에 맞게 슬라이더 위치 애니메이션
* 무한 루프 슬라이딩을 위한 위치 보정 처리 포함
*/
function moveSlide() {
// 애니메이션으로 슬라이더 위치 이동
$slider.animate({'margin-left': -currentSlide * slideWidth}, 500, function() {
// 애니메이션 완료 후 위치 보정 (무한 루프 구현)
if (currentSlide >= totalSlides - 1) {
// 마지막 슬라이드(복제본)에 도달하면 첫 번째 실제 슬라이드로 위치 즉시 이동
currentSlide = 1;
$slider.css('margin-left', -slideWidth);
} else if (currentSlide <= 0) {
// 첫 번째 슬라이드(복제본)에 도달하면 마지막 실제 슬라이드로 위치 즉시 이동
currentSlide = totalSlides - 2;
$slider.css('margin-left', -currentSlide * slideWidth);
}
});
}
// 드래그 관련 상태 변수
let isDragging = false; // 드래그 중인지 여부
let startPos = 0; // 드래그 시작 위치 (X좌표)
let currentPos = 0; // 현재 슬라이더 위치
/**
* 드래그 시작 처리 함수
* 드래그 시작 위치와 현재 슬라이더 위치 기록
* @param {Event} e - 마우스 또는 터치 이벤트
*/
function startDrag(e) {
isDragging = true;
// 마우스 또는 터치 이벤트의 X좌표 가져오기
startPos = e.pageX || e.originalEvent.touches[0].pageX;
// 현재 슬라이더 위치 기록
currentPos = $slider.css('margin-left');
// 자동 슬라이드 정지
stopAutoSlide();
}
/**
* 드래그 중 처리 함수
* 마우스/터치 위치에 따라 슬라이더 위치 실시간 업데이트
* @param {Event} e - 마우스 또는 터치 이벤트
*/
function drag(e) {
if (!isDragging) return; // 드래그 중이 아니면 무시
// 현재 마우스/터치 위치 가져오기
let currentMousePos = e.pageX || e.originalEvent.touches[0].pageX;
// 시작 위치와의 차이 계산
let diff = currentMousePos - startPos;
// 슬라이더 위치 실시간 업데이트
$slider.css('margin-left', parseInt(currentPos) + diff);
}
/**
* 드래그 종료 처리 함수
* 드래그 방향과 거리에 따라 슬라이드 이동 또는 원위치
* @param {Event} e - 마우스 또는 터치 이벤트
*/
function endDrag(e) {
if (!isDragging) return; // 드래그 중이 아니면 무시
isDragging = false;
// 마우스/터치 종료 위치 가져오기
let endPos = e.pageX || e.originalEvent.changedTouches[0].pageX;
// 시작 위치와의 차이 계산
let diff = endPos - startPos;
// 슬라이드 전환을 위한 최소 드래그 거리(50px) 이상이면 슬라이드 전환
if (Math.abs(diff) > 50) {
// 오른쪽으로 드래그: 이전 슬라이드, 왼쪽으로 드래그: 다음 슬라이드
currentSlide += (diff > 0) ? -1 : 1;
moveSlide();
} else {
// 최소 거리 미만이면 원래 위치로 되돌리기
$slider.animate({'margin-left': currentPos}, 200);
}
// 자동 슬라이드 재시작
startAutoSlide();
}
/**
* 공유 링크 생성 함수
* 할인 공유를 위한 고유 링크 생성 및 모달에 표시
* @param {number} bnfInnb - 혜택 고유 번호
*/
function copyLink(bnfInnb) {
$.ajax({
url: '/sopmal/bnft/copyDiscsharLink', // 공유 링크 생성 API
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({ bnfInnb: bnfInnb }), // 혜택 고유 번호 전달
success: function(response) {
if (response.success && response.links && response.links.length > 0) {
// 성공 시 첫 번째 링크 정보 사용
const link = response.links[0];
// 생성된 고유 URL을 입력 필드에 설정
$('#linkToCopy').val(link.uniqueUrl);
// 링크 만료일 표시 형식 변환
const validDate = new Date(link.validDt);
const formattedDate = validDate.toISOString().split('T')[0];
$('#linkExpiryDate').text(formattedDate);
// 링크 복사 모달 표시
MicroModal.show('modal-1');
} else {
// 링크 정보 없음 알림
alert('유효한 링크 정보가 없습니다.');
}
},
error: function(xhr, status, error) {
// 통신 오류 처리
console.error('서버 통신 오류:', error);
alert('서버 통신 중 오류가 발생했습니다.');
}
});
}
/**
* 공유 결과 확인 함수
* 사용자의 할인 공유 결과에 따라 적절한 모달 표시
*/
function showShareResult() {
$.ajax({
url: '/sopmal/bnft/checkDiscsharResult', // 공유 결과 확인 API
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({}),
success: function(response) {
// 공유 링크로 구매한 사람이 있는지 여부에 따라 다른 모달 표시
if (response.hasPurchase) {
// 구매자가 있는 경우 (성공)
MicroModal.show('modal-3');
} else {
// 구매자가 없는 경우 (아직 공유 중)
MicroModal.show('modal-2');
}
},
error: function() {
// 통신 오류 처리
alert('공유 결과를 확인하는데 실패했습니다.');
}
});
}
// 모듈의 공개 인터페이스
return {
init: init, // 모듈 초기화
copyLink: copyLink, // 공유 링크 생성
showShareResult: showShareResult // 공유 결과 확인
};
})();
/**
* 문서 로드 완료 시 실행
* Discshar 모듈 초기화
*/
$(document).ready(function() {
Discshar.init();
});