first commit 2

This commit is contained in:
hmw1001
2026-06-11 18:47:38 +09:00
parent c768729ce6
commit 6f534e33a6
11095 changed files with 1595758 additions and 0 deletions
@@ -0,0 +1,147 @@
/* pns_visual_borad module style */
/* 💡 [수정] 슬라이더 크기를 이미지 원본 크기(1240x750)에 맞춤 */
.pns-visual-slider {
width: 100%;
max-width: 1240px; /* 최대 너비 제한 */
height: 750px; /* 높이 고정 (PC 기준) */
margin: 0 auto; /* 중앙 정렬 */
position: relative;
overflow: hidden;
background: #000;
}
/* 💡 [수정] 이미지를 꽉 채우되(cover), 컨테이너가 이미지 비율과 같으므로 잘리지 않음 */
.visual-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: 100% 100% ;
background-position: center;
background-repeat: no-repeat;
/*transition: transform 7s;*/
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
-ms-interpolation-mode: bicubic;
}
.swiper-slide-active .visual-bg { transform: scale(1.1); } /* 미세한 줌 효과 */
/* 오버레이 제거 (투명) */
.visual-bg::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0);
pointer-events: none;
}
.visual-content { position: relative; z-index: 10; height: 100%; display: flex; flex-direction: column; justify-content: center; color: #fff; padding: 0 10%; }
.visual-title { font-size: 3.5rem; font-weight: 800; line-height: 1.2; margin-bottom: 20px; word-break: keep-all; text-shadow: 2px 2px 10px rgba(0,0,0,0.5); }
.visual-desc { font-size: 1.3rem; line-height: 1.6; margin-bottom: 40px; font-weight: 300; opacity: 0.9; text-shadow: 1px 1px 5px rgba(0,0,0,0.5); }
.visual-btn { display: inline-block; padding: 15px 45px; border: 2px solid #fff; color: #fff; text-decoration: none; font-size: 1rem; transition: 0.3s; width: fit-content; cursor: pointer; }
.visual-btn:hover { background: #fff; color: #000; }
/* 라이트박스 스타일 */
.image-lightbox {
display: none;
position: fixed;
z-index: 9999;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.85);
justify-content: center;
align-items: center;
animation: fadeIn 0.3s;
flex-direction: column;
}
.lightbox-content {
max-width: 90%;
max-height: 80%;
object-fit: contain;
animation: zoomIn 0.3s;
cursor: pointer;
}
.lightbox-close {
position: absolute;
top: 20px;
right: 40px;
color: #fff;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
cursor: pointer;
z-index: 10001;
}
.lightbox-close:hover {
color: #bbb;
}
/* 라이트박스 내 바로가기 버튼 스타일 */
.lightbox-link-btn {
display: none;
margin-top: 20px;
padding: 12px 30px;
background-color: #009fe3;
color: #fff;
text-decoration: none;
font-size: 16px;
font-weight: bold;
border-radius: 5px;
transition: background-color 0.3s;
z-index: 10001;
}
.lightbox-link-btn:hover {
background-color: #007bb5;
}
/* Swiper 네비게이션 버튼 스타일 */
.swiper-button-next, .swiper-button-prev {
color: #fff !important;
text-shadow: 0 0 5px rgba(0,0,0,0.5);
}
.swiper-pagination-bullet {
background: #fff !important;
opacity: 0.5;
}
.swiper-pagination-bullet-active {
opacity: 1;
background: #009fe3 !important;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes zoomIn {
from { transform: scale(0.8); }
to { transform: scale(1); }
}
/* 💡 [수정] 모바일 반응형 처리 (비율 유지) */
@media (max-width: 1240px) {
.pns-visual-slider {
height: auto;
aspect-ratio: 1240 / 750; /* 비율 유지 */
}
}
@media (max-width: 768px) {
.visual-title { font-size: 2rem; }
.visual-desc { font-size: 1rem; }
}
@@ -0,0 +1,66 @@
(function($) {
"use strict";
if (typeof window.initPremiumAdSection === 'function') {
// return;
}
window.initPremiumAdSection = function(moduleId) {
const $module = $('#' + moduleId);
if (!$module.length) return;
$module.find('.premium-ad-row').each(function() {
const $row = $(this);
const $swiperContainer = $row.find('.swiper-container');
// 설정된 컬럼 수 (예: 6)
const configColumns = parseInt($swiperContainer.data('slides-per-view'), 10) || 6;
const spaceBetween = parseInt($swiperContainer.data('space-between'), 10) || 10;
// 실제 슬라이드 개수 (예: 3)
const totalSlides = $swiperContainer.find('.swiper-slide').length;
// 💡 [핵심 수정] 슬라이드 개수가 설정된 컬럼 수보다 적으면, 개수만큼만 보여줘서 꽉 채움
// 예: 6개 설정인데 3개만 있다면, 3개를 100% 너비로 꽉 채워서 보여줌
let slidesPerViewPC = configColumns;
if (totalSlides > 0 && totalSlides < configColumns) {
slidesPerViewPC = totalSlides;
}
// 슬라이드가 1개면 롤링 안 함, 2개 이상이면 무조건 롤링
const loop = totalSlides > 1;
new Swiper($swiperContainer[0], {
slidesPerView: 2, // 모바일 기본값
spaceBetween: spaceBetween,
loop: loop,
autoplay: {
delay: 3000,
disableOnInteraction: false,
},
navigation: {
nextEl: $row.find('.swiper-button-next')[0],
prevEl: $row.find('.swiper-button-prev')[0],
},
breakpoints: {
640: {
slidesPerView: (totalSlides < 3) ? totalSlides : 3
},
768: {
slidesPerView: (totalSlides < 4) ? totalSlides : 4
},
1024: {
// 💡 PC에서는 계산된 slidesPerViewPC 사용
slidesPerView: slidesPerViewPC
}
}
});
});
};
$(function() {
$('.premium-ad-section').each(function() {
window.initPremiumAdSection($(this).attr('id'));
});
});
})(jQuery);
@@ -0,0 +1,232 @@
<?php
if (!defined('_GNUBOARD_')) exit;
/**
* rb.custom :: pns_visual_borad/module.php
* PNS 스타일 메인 비주얼 슬라이더 (게시판 연동)
*/
if (!isset($md_id) || !$md_id) return;
$md_id_safe = sql_real_escape_string($md_id);
$module_config = sql_fetch(" SELECT * FROM `rb_module` WHERE md_id = '{$md_id_safe}' ");
if (!$module_config) $module_config = sql_fetch(" SELECT * FROM `rb_module_shop` WHERE md_id = '{$md_id_safe}' ");
if (!$module_config) return;
$config_path = __DIR__ . '/config.php';
if (file_exists($config_path)) include_once($config_path);
// --- 설정 변수 ---
$bo_table = 'main_visual'; // 실제 생성하신 게시판 테이블명으로 수정하세요
$limit_count = 10; // 불러올 슬라이드 개수 (변수 처리)
$write_table = $g5['write_prefix'] . $bo_table;
// 💡 [설정] 애니메이션(Parallax) 사용 여부 (true: 사용, false: 사용안함 - 이미지 고정)
$use_parallax = false;
// 💡 [추가] 팝업 내 링크 이동 방식 설정 (button, image, both)
$link_type = 'image'; // 기본값: 이미지 클릭 시 이동
// 💡 [수정] 노출 조건 추가 (숨김, 예약 노출)
$today = G5_TIME_YMD; // 오늘 날짜 (YYYY-MM-DD)
$sql_where = " wr_is_comment = 0 "; // 기본 조건: 댓글 제외
// 1. 숨김 설정 (wr_10) 체크: 값이 없거나 0인 경우만 노출
$sql_where .= " AND (wr_10 = '' OR wr_10 IS NULL OR wr_10 = '0') ";
// 2. 노출 방식 (wr_9) 체크: 즉시 노출이거나, 예약 기간 내인 경우
$sql_where .= " AND (
wr_9 != 'RESERVED'
OR (wr_9 = 'RESERVED' AND wr_2 <= '{$today}' AND wr_3 >= '{$today}')
) ";
// 데이터베이스에서 데이터 가져오기 (wr_id 역순)
$sql = " SELECT * FROM {$write_table}
WHERE {$sql_where}
ORDER BY wr_num, wr_reply LIMIT 0, {$limit_count} ";
$result = sql_query($sql);
$module_id = 'pns_visual_' . uniqid();
?>
<div id="<?php echo $module_id; ?>" class="pns-visual-slider swiper-container">
<div class="swiper-wrapper">
<?php
for ($i=0; $row=sql_fetch_array($result); $i++) {
// 💡 [수정] 이미지 가져오기 로직 개선 (원본 파일 우선 -> 썸네일 -> 기본 이미지)
$img_url = '';
// 1. 원본 파일 확인
$sql_file = " select bf_file from {$g5['board_file_table']} where bo_table = '$bo_table' and wr_id = '{$row['wr_id']}' order by bf_no limit 1 ";
$row_file = sql_fetch($sql_file);
if ($row_file['bf_file']) {
$img_url = G5_DATA_URL.'/file/'.$bo_table.'/'.$row_file['bf_file'];
}
// 2. 원본 파일이 없으면 썸네일 확인
if (!$img_url) {
$thumb = get_list_thumbnail($bo_table, $row['wr_id'], '1240', '750', true, true);
if ($thumb['src']) {
$img_url = $thumb['src'];
}
}
// 3. 둘 다 없으면 기본 이미지
if (!$img_url) {
$img_url = G5_THEME_URL.'/rb.img/no_image.png';
}
// 원본 이미지 경로 (팝업용)
$ori_url = $img_url;
// 제목과 요약 내용 (wr_subject, wr_1)
$subject = cut_str(get_text($row['wr_subject']), 100);
$summary = get_text($row['wr_1']); // wr_1에 저장된 요약 내용
// 링크 URL (wr_link1 사용)
$link_url = $row['wr_link1'];
// 💡 [수정] 링크가 있으면 바로 이동, 없으면 팝업
$click_action = '';
$cursor_style = '';
if ($link_url) {
$click_action = "onclick=\"window.open('{$link_url}', '_blank');\"";
$cursor_style = 'cursor: pointer;';
} else {
$click_action = "onclick=\"openLightbox('{$ori_url}');\""; // 팝업 함수 호출
$cursor_style = 'cursor: zoom-in;';
}
?>
<div class="swiper-slide">
<!-- 💡 [수정] 배경 이미지에 클릭 이벤트 추가 및 텍스트 숨김 -->
<!-- Parallax 효과가 켜져있을 때만 data-swiper-parallax 속성 추가 -->
<div class="visual-bg"
style="background-image: url('<?php echo $img_url; ?>'); <?php echo $cursor_style; ?>"
<?php echo $click_action; ?>
<?php if($use_parallax) echo 'data-swiper-parallax="50%"'; ?>
></div>
<!-- 텍스트와 버튼은 숨김 처리 (필요시 주석 해제) -->
<!--
<div class="visual-content container">
<h2 class="visual-title" <?php if($use_parallax) echo 'data-swiper-parallax="-300"'; ?>><?php echo nl2br($subject); ?></h2>
<p class="visual-desc" <?php if($use_parallax) echo 'data-swiper-parallax="-200"'; ?>><?php echo nl2br($summary); ?></p>
<a href="javascript:void(0);" class="visual-btn btn-open-lightbox" data-img="<?php echo $ori_url; ?>" data-url="<?php echo $link_url; ?>" <?php if($use_parallax) echo 'data-swiper-parallax="-100"'; ?>>자세히 보기</a>
</div>
-->
</div>
<?php } ?>
<?php if($i == 0) echo '<div class="swiper-slide"><div class="visual-content">등록된 광고 데이터가 없습니다.</div></div>'; ?>
</div>
<div class="swiper-pagination"></div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
</div>
<!-- 💡 [추가] 이미지 라이트박스 컨테이너 -->
<div id="image-lightbox" class="image-lightbox">
<span class="lightbox-close">&times;</span>
<img class="lightbox-content" id="lightbox-img">
<!-- 💡 [추가] 바로가기 버튼 -->
<a href="#" target="_blank" class="lightbox-link-btn" id="lightbox-link">바로가기</a>
</div>
<!-- CSS 파일 로드 -->
<link rel="stylesheet" href="<?php echo G5_THEME_URL; ?>/rb.custom/pns_visual_borad/module.css?ver=<?php echo G5_CSS_VER; ?>">
<!-- 통합 동적 로더 (Swiper) -->
<script>
// 전역 함수로 선언하여 HTML onclick에서 호출 가능하게 함
function openLightbox(imgSrc, linkUrl) {
var lightbox = document.getElementById('image-lightbox');
var lightboxImg = document.getElementById('lightbox-img');
var lightboxLink = document.getElementById('lightbox-link');
if (imgSrc) {
lightboxImg.src = imgSrc;
if (linkUrl && linkUrl !== "") {
lightboxLink.href = linkUrl;
lightboxLink.style.display = 'inline-block';
lightboxImg.onclick = function() {
window.open(linkUrl, '_blank');
};
lightboxImg.style.cursor = 'pointer';
} else {
lightboxLink.style.display = 'none';
lightboxImg.onclick = null;
lightboxImg.style.cursor = 'default';
}
lightbox.style.display = 'flex';
}
}
(function() {
var currentModuleId = '<?php echo $module_id; ?>';
var themeUrl = '<?php echo G5_THEME_URL; ?>';
var jsVer = '<?php echo G5_JS_VER; ?>';
var linkType = '<?php echo $link_type; ?>'; // 💡 [추가] 링크 이동 방식 플래그
var useParallax = <?php echo $use_parallax ? 'true' : 'false'; ?>; // PHP 변수를 JS로 전달
function loadScript(src, id, callback) {
if (document.getElementById(id)) {
if (callback) callback();
return;
}
var script = document.createElement('script');
script.id = id;
script.src = src;
script.async = false;
if (callback) {
script.onload = callback;
}
document.head.appendChild(script);
}
function initSwiper() {
new Swiper('#' + currentModuleId, {
speed: 1200,
// parallax: useParallax, // 💡 [수정] 변수로 제어
loop: true,
autoplay: { delay: 6000, disableOnInteraction: false },
pagination: { el: '.swiper-pagination', clickable: true },
navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' },
});
// 라이트박스 제어 스크립트
var lightbox = document.getElementById('image-lightbox');
var closeBtn = document.querySelector('.lightbox-close');
if (closeBtn) {
closeBtn.addEventListener('click', function() {
lightbox.style.display = 'none';
});
}
if (lightbox) {
lightbox.addEventListener('click', function(e) {
if (e.target === lightbox) {
lightbox.style.display = 'none';
}
});
}
}
if (typeof Swiper === 'undefined') {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://unpkg.com/swiper/swiper-bundle.min.css';
document.head.appendChild(link);
loadScript('https://unpkg.com/swiper/swiper-bundle.min.js', 'swiper-bundle-js', initSwiper);
} else {
initSwiper();
}
})();
</script>