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,125 @@
/* pns_visual_borad_fix module style */
/* 💡 [수정] 독립적인 스타일 적용을 위해 고유 클래스 사용 */
.pns-fix-board {
width: 100%;
max-width: 100%; /* 부모 영역에 맞춤 */
margin: 0 auto;
box-sizing: border-box;
}
/*.pns-fix-list {*/
/* display: flex;*/
/* flex-wrap: wrap;*/
/* gap: 10px; !* 아이템 간 간격 *!*/
/* width: 100%;*/
/*}*/
.pns-fix-list{
display: grid !important;
grid-template-columns: repeat(2, 1fr) !important;
gap: 10px !important;
width: 100% !important;
box-sizing: border-box !important;
}
.pns-fix-item {
/* 4개를 한 줄에 배치 (간격 고려) */
width: calc(25% - 7.5px);
box-sizing: border-box;
position: relative;
overflow: hidden;
border-radius: 8px; /* 모서리 둥글게 (선택) */
background: #f0f0f0;
}
/* 이미지 비율 유지 및 꽉 채우기 */
.pns-fix-img-wrap {
width: 100%;
height: 0;
padding-bottom: calc(75% - 20px); /* 4:3 비율 예시 (원하는 비율로 조정 가능) */
position: relative;
overflow: hidden;
transition: transform 0.3s ease;
}
.pns-fix-img-wrap img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover; /* 이미지를 영역에 꽉 채움 */
transition: transform 0.5s ease;
}
/* 호버 효과 */
.pns-fix-img-wrap:hover img {
transform: scale(1.05);
}
.pns-fix-no-data {
width: 100%;
padding: 50px 0;
text-align: center;
/*background: #eee;*/
color: #000000;
}
/* --- 라이트박스 스타일 (독립적) --- */
.pns-fix-lightbox {
display: none;
position: fixed;
z-index: 99999; /* 매우 높게 설정 */
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
justify-content: center;
align-items: center;
flex-direction: column;
}
.pns-fix-lightbox-content {
max-width: 90%;
max-height: 80vh;
object-fit: contain;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
}
.pns-fix-close {
position: absolute;
top: 30px;
right: 40px;
color: #fff;
font-size: 50px;
font-weight: bold;
cursor: pointer;
line-height: 1;
}
.pns-fix-link-btn {
margin-top: 20px;
padding: 10px 25px;
background-color: #009fe3;
color: #fff;
text-decoration: none;
border-radius: 4px;
font-weight: bold;
}
/* --- 반응형 처리 --- */
/* 태블릿: 2개씩 배치 */
@media (max-width: 1024px) {
.pns-fix-item {
width: calc(50% - 5px);
}
}
/* 모바일: 1개씩 배치 */
@media (max-width: 640px) {
.pns-fix-item {
width: 100%;
}
}
@@ -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,242 @@
<?php
if (!defined('_GNUBOARD_')) exit;
/**
* rb.custom :: pns_visual_borad_fix/module.php
* PNS 고정형 광고 보드 (게시판 연동)
*/
if (!isset($md_id) || !$md_id) return;
// 💡 [핵심] 라이브러리 함수를 사용하여 모듈 설정 로드
$md_id_safe = sql_real_escape_string($md_id);
$module_config = get_rb_module_config($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_2'; // 실제 생성하신 게시판 테이블명으로 수정하세요
// 💡 [수정] 불러올 개수 설정 (모듈 설정 연동)
$md_cnt = isset($module_config['md_cnt']) ? (int)$module_config['md_cnt'] : 0;
$md_col = isset($module_config['md_col']) ? (int)$module_config['md_col'] : 4; // 기본값 4
$md_row = isset($module_config['md_row']) ? (int)$module_config['md_row'] : 1; // 기본값 1
$md_col_mo = isset($module_config['md_col_mo']) ? (int)$module_config['md_col_mo'] : 1; // 모바일 기본값 1
// 💡 [수정] 간격(마진) 기본값 증가 (10 -> 20)
$md_gap = (isset($module_config['md_gap']) && $module_config['md_gap'] !== '') ? (int)$module_config['md_gap'] : 20;
$md_gap_mo = (isset($module_config['md_gap_mo']) && $module_config['md_gap_mo'] !== '') ? (int)$module_config['md_gap_mo'] : 15;
if ($md_cnt > 0) {
$limit_count = $md_cnt;
} elseif ($md_col > 0 && $md_row > 0) {
$limit_count = $md_col * $md_row;
} else {
$limit_count = 4;
}
// 썸네일 출력 여부
$is_thumb = isset($module_config['md_thumb_is']) ? $module_config['md_thumb_is'] : '1';
$write_table = $g5['write_prefix'] . $bo_table;
// 💡 [추가] 팝업 내 링크 이동 방식 설정 (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);
// 고유 ID 생성 (스타일 격리용)
$module_uid = 'pns_fix_' . uniqid();
?>
<!-- CSS 파일 로드 -->
<link rel="stylesheet" href="<?php echo G5_THEME_URL; ?>/rb.custom/pns_visual_borad_fix/module.css?ver=<?php echo G5_CSS_VER; ?>">
<!-- 💡 [수정] CSS Grid를 사용하여 겹침 방지 및 자동 정렬 -->
<style>
#<?php echo $module_uid; ?> .pns-fix-list {
display: grid;
grid-template-columns: repeat(<?php echo $md_col; ?>, 1fr);
gap: <?php echo $md_gap; ?>px; /* 아이템 사이 간격 */
width: 100%;
box-sizing: border-box;
}
#<?php echo $module_uid; ?> .pns-fix-item {
width: 100%; /* 그리드 셀에 꽉 차게 */
min-width: 0; /* 그리드 오버플로우 방지 */
overflow: hidden; /* 💡 자식 요소가 넘치지 않도록 숨김 */
border-radius: 8px; /* 💡 모서리 둥글게 강제 적용 */
background: #fff;
position: relative;
}
/* 이미지 래퍼: 비율 유지 및 리사이징 */
#<?php echo $module_uid; ?> .pns-fix-img-wrap {
width: 100%;
position: relative;
padding-bottom: 75%; /* 4:3 비율 (필요시 조정 가능) */
overflow: hidden; /* 💡 이미지 넘침 방지 */
}
#<?php echo $module_uid; ?> .pns-fix-img-wrap img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
max-width: 100%; /* 💡 안전장치 */
object-fit: cover; /* 비율 유지하며 꽉 채우기 */
transition: transform 0.5s ease;
}
/* 호버 시 확대 효과 (선택 사항) */
#<?php echo $module_uid; ?> .pns-fix-img-wrap:hover img {
transform: scale(1.05);
}
@media (max-width: 768px) {
#<?php echo $module_uid; ?> .pns-fix-list {
grid-template-columns: repeat(<?php echo $md_col_mo; ?>, 1fr);
gap: <?php echo $md_gap_mo; ?>px;
}
}
</style>
<div id="<?php echo $module_uid; ?>" class="pns-fix-board">
<div class="pns-fix-list">
<?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;
$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=\"pnsOpenLightbox('{$ori_url}');\""; // 함수명 변경
$cursor_style = 'cursor: zoom-in;';
}
?>
<div class="pns-fix-item">
<div class="pns-fix-img-wrap"
style="<?php echo $cursor_style; ?>"
<?php echo $click_action; ?>>
<?php if ($is_thumb == '1') { ?>
<img src="<?php echo $img_url; ?>" alt="<?php echo get_text($row['wr_subject']); ?>">
<?php } ?>
</div>
</div>
<?php } ?>
<?php
// 데이터가 없을 경우 빈 박스 처리 (선택 사항)
if($i == 0) echo '<div class="pns-fix-no-data">등록된 광고 데이터가 없습니다.</div>';
?>
</div>
</div>
<!-- 💡 [추가] 이미지 라이트박스 컨테이너 (독립적 ID 사용) -->
<div id="pns-fix-lightbox" class="pns-fix-lightbox">
<span class="pns-fix-close">&times;</span>
<img class="pns-fix-lightbox-content" id="pns-fix-lightbox-img">
<a href="#" target="_blank" class="pns-fix-link-btn" id="pns-fix-lightbox-link">바로가기</a>
</div>
<script>
// 💡 [수정] 전역 함수 충돌 방지를 위해 이름 변경
function pnsOpenLightbox(imgSrc, linkUrl) {
var lightbox = document.getElementById('pns-fix-lightbox');
var lightboxImg = document.getElementById('pns-fix-lightbox-img');
var lightboxLink = document.getElementById('pns-fix-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 lightbox = document.getElementById('pns-fix-lightbox');
var closeBtn = document.querySelector('.pns-fix-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';
}
});
}
})();
</script>