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,15 @@
<?php
if (!defined('_GNUBOARD_')) exit;
/**
* rb.custom :: rolling_banner_footer/config.php
* 하단 롤링 배너 모듈 설정 파일
*/
$rolling_banner_config = [
'position' => 'rolling_footer', // 배너 위치 (관리자 페이지에서 등록한 위치)
'timeout' => 3000, // 롤링 간격 (밀리초)
'speed' => 1000, // 슬라이드 속도
'visible' => 6, // 한 번에 보여줄 배너 개수 (PC 기준)
];
?>
@@ -0,0 +1,99 @@
/* Rolling Banner Footer Style - Final Button Fix */
.rolling-banner-footer {
background-color: #ffffff;
padding: 20px 0;
border-top: 1px solid #eee;
}
.rolling-banner-wrap {
position: relative;
padding: 0 50px;
height: 60px;
overflow: hidden;
}
/*.swiper-container {*/
/* width: 100%;*/
/* height: 100%;*/
/*}*/
/* 💡 [핵심 수정] 고정 너비 삭제 */
.swiper-slide.banner-item {
/* width: 160px; */ /* Swiper가 자동으로 계산하도록 삭제 */
text-align: center;
}
.banner-item a {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.banner-item img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
transition: opacity 0.3s;
}
.banner-item a:hover img {
opacity: 0.8;
}
.slider-controls .swiper-button-prev,
.slider-controls .swiper-button-next {
color: #fff;
width: 40px;
height: 40px;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
margin-top: 0;
}
.slider-controls .swiper-button-prev:after,
.slider-controls .swiper-button-next:after {
font-size: 16px;
font-weight: bold;
}
.slider-controls .swiper-button-prev {
left: 0;
}
.slider-controls .swiper-button-next {
right: 0;
}
.empty-banner {
text-align: center;
padding: 20px;
color: #fff;
line-height: 60px;
}
/* 💡 [수정] 제목 영역 스타일 (밑줄 강화 및 위치 수정) */
.rolling-banner-footer .bbs_main_wrap_tit {
margin-bottom: 20px;
border-bottom: 2px solid #333; /* 💡 밑줄 두께 2px, 색상 진하게(#333) */
padding-bottom: 7px; /* 💡 [수정] 밑줄과 텍스트 사이 간격 줄임 (15px -> 7px) */
overflow: hidden; /* 💡 float 해제 (높이 잡기) */
}
.rolling-banner-footer .bbs_main_wrap_tit_l {
float: left;
}
.rolling-banner-footer .bbs_main_wrap_tit_r {
float: right;
padding-top: 5px; /* 버튼 위치 미세 조정 */
}
.rolling-banner-footer .cb {
clear: both;
}
@@ -0,0 +1,61 @@
(function($) {
"use strict";
if (typeof window.initRollingBannerFooter === 'function') {
// return;
}
window.initRollingBannerFooter = function(moduleId) {
const $module = $('#' + moduleId);
if (!$module.length) return;
const $swiperContainer = $module.find('.swiper-container');
const autoplayDelay = parseInt($swiperContainer.data('autoplay-delay'), 10) || 3000;
const slidesPerViewPC = parseInt($swiperContainer.data('slides-per-view'), 10) || 6;
const bannerCount = parseInt($swiperContainer.data('banner-count'), 10) || 0;
// 💡 [핵심 수정] 배너 개수가 화면에 보여줄 개수보다 많을 때만 loop를 활성화
const isLoop = bannerCount > slidesPerViewPC;
new Swiper($swiperContainer[0], {
spaceBetween: 20,
loop: isLoop, // 💡 [수정] 동적으로 loop 설정
autoplay: {
delay: autoplayDelay,
disableOnInteraction: false,
},
navigation: {
nextEl: $module.find('.swiper-button-next')[0],
prevEl: $module.find('.swiper-button-prev')[0],
},
observer: true,
observeParents: true,
// 💡 [핵심 수정] 반응형 Breakpoints 설정
breakpoints: {
// 320px 이상일 때
320: {
slidesPerView: 3,
spaceBetween: 10
},
// 768px 이상일 때 (태블릿)
768: {
slidesPerView: 4,
spaceBetween: 20
},
// 1024px 이상일 때 (PC)
1024: {
slidesPerView: slidesPerViewPC,
spaceBetween: 20
},
}
});
};
$(function() {
$('.rolling-banner-footer').each(function() {
window.initRollingBannerFooter($(this).attr('id'));
});
});
})(jQuery);
@@ -0,0 +1,58 @@
(function($) {
"use strict";
if (typeof window.initRollingBannerFooter === 'function') {
// return;
}
window.initRollingBannerFooter = function(moduleId) {
const $module = $('#' + moduleId);
if (!$module.length) return;
const $swiperContainer = $module.find('.swiper-container');
const autoplayDelay = parseInt($swiperContainer.data('autoplay-delay'), 10) || 3000;
const slidesPerViewPC = parseInt($swiperContainer.data('slides-per-view'), 10) || 6;
new Swiper($swiperContainer[0], {
// slidesPerView: 'auto', // 💡 [삭제] 자동 너비 대신 개수 지정
spaceBetween: 20,
loop: true,
autoplay: {
delay: autoplayDelay,
disableOnInteraction: false,
},
navigation: {
nextEl: $module.find('.swiper-button-next')[0],
prevEl: $module.find('.swiper-button-prev')[0],
},
observer: true,
observeParents: true,
// 💡 [핵심 수정] 반응형 Breakpoints 설정
breakpoints: {
// 320px 이상일 때
320: {
slidesPerView: 3,
spaceBetween: 10
},
// 768px 이상일 때 (태블릿)
768: {
slidesPerView: 4,
spaceBetween: 20
},
// 1024px 이상일 때 (PC)
1024: {
slidesPerView: slidesPerViewPC,
spaceBetween: 20
},
}
});
};
$(function() {
$('.rolling-banner-footer').each(function() {
window.initRollingBannerFooter($(this).attr('id'));
});
});
})(jQuery);
@@ -0,0 +1,121 @@
<?php
if (!defined('_GNUBOARD_')) exit;
// 1. 설정 파일 로드
$config_path = __DIR__ . '/config.php';
if (!file_exists($config_path)) return;
include_once($config_path);
include_once(G5_LIB_PATH.'/thumbnail.lib.php');
// 💡 [핵심] $md_id 변수를 사용하여 모듈 설정 로드
if (isset($md_id) && $md_id) {
$rb_skin = get_rb_module_config($md_id);
} else {
$rb_skin = array(); // md_id가 없을 경우 빈 배열
}
// 2. 데이터 가져오기
$position = $rolling_banner_config['position'];
$sql = " SELECT * FROM `rb_banner` WHERE bn_position = '{$position}' AND bn_begin_time <= NOW() AND bn_end_time >= NOW() ORDER BY bn_order ASC, bn_id DESC ";
$result = sql_query($sql);
$banners = [];
while ($row = sql_fetch_array($result)) {
$banners[] = $row;
}
$banner_count = count($banners); // 💡 [추가] 배너 개수 저장
$visual_id = 'rbf_' . uniqid();
?>
<div class="rolling-banner-footer" id="<?php echo $visual_id; ?>">
<ul class="bbs_main_wrap_tit" style="display:<?php echo (isset($rb_skin['md_title_hide']) && $rb_skin['md_title_hide'] == '1') ? 'none' : 'block'; ?>">
<li class="bbs_main_wrap_tit_l">
<a href="<?php echo $links_url; ?>">
<h2 class="<?php echo isset($rb_skin['md_title_font']) ? $rb_skin['md_title_font'] : 'font-B'; ?>" style="color:<?php echo isset($rb_skin['md_title_color']) ? $rb_skin['md_title_color'] : '#25282b'; ?>; font-size:<?php echo isset($rb_skin['md_title_size']) ? $rb_skin['md_title_size'] : '20'; ?>px; "><?php echo isset($rb_skin['md_title']) ? $rb_skin['md_title'] : '하단 롤링 배너'; ?></h2>
</a>
</li>
<div class="cb"></div>
</ul>
<div class="rolling-banner-wrap">
<!-- 💡 [핵심 수정] Swiper 구조로 변경 -->
<div class="swiper-container rolling-swiper"
data-autoplay-delay="<?php echo $rolling_banner_config['timeout']; ?>"
data-slides-per-view="<?php echo $rolling_banner_config['visible']; ?>"
data-banner-count="<?php echo $banner_count; ?>">
<div class="swiper-wrapper">
<?php foreach ($banners as $banner):
$bimg = G5_DATA_PATH.'/banners/'.$banner['bn_id'];
if (!file_exists($bimg)) continue;
$img_src = G5_DATA_URL.'/banners/'.$banner['bn_id'];
?>
<div class="swiper-slide banner-item">
<a href="<?php echo $banner['bn_url']; ?>" target="<?php echo $banner['bn_new_win'] ? '_blank' : '_self'; ?>">
<img src="<?php echo $img_src; ?>" alt="<?php echo get_text($banner['bn_alt']); ?>">
</a>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="slider-controls">
<div class="swiper-button-prev btn-prev"><i class="fa fa-chevron-left"></i></div>
<div class="swiper-button-next btn-next"><i class="fa fa-chevron-right"></i></div>
</div>
<?php if (empty($banners)): ?>
<div class="empty-banner">등록된 배너가 없습니다.</div>
<?php endif; ?>
</div>
</div>
<link rel="stylesheet" href="<?php echo G5_THEME_URL; ?>/rb.custom/rolling_banner_footer/module.css?ver=<?php echo G5_CSS_VER; ?>">
<!-- 통합 동적 로더 -->
<script>
(function() {
var currentModuleId = '<?php echo $visual_id; ?>';
var initFunctionName = 'initRollingBannerFooter';
var themeUrl = '<?php echo G5_THEME_URL; ?>';
var jsVer = '<?php echo G5_JS_VER; ?>';
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 finalAction() {
if (typeof window[initFunctionName] === 'function') {
window[initFunctionName](currentModuleId);
}
}
function loadModuleScript() {
loadScript(themeUrl + '/rb.custom/rolling_banner_footer/module.js?ver=' + jsVer, 'rolling-banner-footer-js', finalAction);
}
// 💡 [핵심] Swiper 라이브러리 로드 확인
if (typeof Swiper === 'undefined') {
// Swiper CSS 로드
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://unpkg.com/swiper/swiper-bundle.min.css';
document.head.appendChild(link);
// Swiper JS 로드
loadScript('https://unpkg.com/swiper/swiper-bundle.min.js', 'swiper-bundle-js', loadModuleScript);
} else {
loadModuleScript();
}
})();
</script>
@@ -0,0 +1,135 @@
<?php
if (!defined('_GNUBOARD_')) exit;
// 1. 설정 파일 로드
$config_path = __DIR__ . '/config.php';
if (!file_exists($config_path)) return;
include_once($config_path);
include_once(G5_LIB_PATH.'/thumbnail.lib.php');
// 💡 [핵심] $md_id 변수를 사용하여 모듈 설정 로드
// 이 파일이 include 될 때 상위 스코프에서 $md_id가 정의되어 있어야 합니다.
// 보통 index.php 등에서 모듈을 호출할 때 $md_id를 설정하고 include 합니다.
if (isset($md_id) && $md_id) {
$rb_skin = get_rb_module_config($md_id);
} else {
$rb_skin = array(); // md_id가 없을 경우 빈 배열
}
// 2. 데이터 가져오기
$position = $rolling_banner_config['position'];
$sql = " SELECT * FROM `rb_banner` WHERE bn_position = '{$position}' AND bn_begin_time <= NOW() AND bn_end_time >= NOW() ORDER BY bn_order ASC, bn_id DESC ";
$result = sql_query($sql);
$banners = [];
while ($row = sql_fetch_array($result)) {
$banners[] = $row;
}
$visual_id = 'rbf_' . uniqid();
?>
<!-- Rebuilder 표준 구조 -->
<!--<div class="rb_layout_box" data-id="rolling_banner_footer">-->
<!-- --><?php //if ($is_admin) { ?>
<!-- <div class="rb_module_set">-->
<!-- <a href="javascript:;" onclick="set_module_send(this);" class="btn_module_setup"><i class="fa fa-cog"></i></a>-->
<!-- </div>-->
<!-- --><?php //} ?>
<div class="rolling-banner-footer" id="<?php echo $visual_id; ?>">
<!-- <div class="container">-->
<!-- { -->
<ul class="bbs_main_wrap_tit" style="display:<?php echo (isset($rb_skin['md_title_hide']) && $rb_skin['md_title_hide'] == '1') ? 'none' : 'block'; ?>">
<li class="bbs_main_wrap_tit_l">
<!-- 타이틀 { -->
<a href="<?php echo $links_url; ?>">
<h2 class="<?php echo isset($rb_skin['md_title_font']) ? $rb_skin['md_title_font'] : 'font-B'; ?>" style="color:<?php echo isset($rb_skin['md_title_color']) ? $rb_skin['md_title_color'] : '#25282b'; ?>; font-size:<?php echo isset($rb_skin['md_title_size']) ? $rb_skin['md_title_size'] : '20'; ?>px; "><?php echo isset($rb_skin['md_title']) ? $rb_skin['md_title'] : '하단 롤링 배너'; ?></h2>
</a>
<!-- } -->
</li>
<div class="cb"></div>
</ul>
<div class="rolling-banner-wrap">
<!-- 💡 [핵심 수정] Swiper 구조로 변경 -->
<div class="swiper-container rolling-swiper"
data-autoplay-delay="<?php echo $rolling_banner_config['timeout']; ?>"
data-slides-per-view="<?php echo $rolling_banner_config['visible']; ?>">
<div class="swiper-wrapper">
<?php foreach ($banners as $banner):
$bimg = G5_DATA_PATH.'/banners/'.$banner['bn_id'];
if (!file_exists($bimg)) continue;
$img_src = G5_DATA_URL.'/banners/'.$banner['bn_id'];
?>
<div class="swiper-slide banner-item">
<a href="<?php echo $banner['bn_url']; ?>" target="<?php echo $banner['bn_new_win'] ? '_blank' : '_self'; ?>">
<img src="<?php echo $img_src; ?>" alt="<?php echo get_text($banner['bn_alt']); ?>">
</a>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="slider-controls">
<div class="swiper-button-prev btn-prev"><i class="fa fa-chevron-left"></i></div>
<div class="swiper-button-next btn-next"><i class="fa fa-chevron-right"></i></div>
</div>
<?php if (empty($banners)): ?>
<div class="empty-banner">등록된 배너가 없습니다.</div>
<?php endif; ?>
</div>
</div>
<link rel="stylesheet" href="<?php echo G5_THEME_URL; ?>/rb.custom/rolling_banner_footer/module.css?ver=<?php echo G5_CSS_VER; ?>">
<!-- 통합 동적 로더 -->
<script>
(function() {
var currentModuleId = '<?php echo $visual_id; ?>';
var initFunctionName = 'initRollingBannerFooter';
var themeUrl = '<?php echo G5_THEME_URL; ?>';
var jsVer = '<?php echo G5_JS_VER; ?>';
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 finalAction() {
if (typeof window[initFunctionName] === 'function') {
window[initFunctionName](currentModuleId);
}
}
function loadModuleScript() {
loadScript(themeUrl + '/rb.custom/rolling_banner_footer/module.js?ver=' + jsVer, 'rolling-banner-footer-js', finalAction);
}
// 💡 [핵심] Swiper 라이브러리 로드 확인
if (typeof Swiper === 'undefined') {
// Swiper CSS 로드
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://unpkg.com/swiper/swiper-bundle.min.css';
document.head.appendChild(link);
// Swiper JS 로드
loadScript('https://unpkg.com/swiper/swiper-bundle.min.js', 'swiper-bundle-js', loadModuleScript);
} else {
loadModuleScript();
}
})();
</script>