Files
dnssash/theme/rd.laser/skin/board/rb.board.core.coverage/view.skin.php
T
2026-06-11 18:47:38 +09:00

232 lines
8.0 KiB
PHP

<?php
if (!defined('_GNUBOARD_')) exit;
/**
* rb.board.core.coverage :: view.skin.php
* '심층취재' 타입 전용 뷰어 - 본문/이미지 출력 및 콘텐츠 타입에 따른 렌더링 담당
*/
// 스킨 CSS 로드
$_skin_url = G5_THEME_URL . '/skin/board/rb.board.core.coverage';
add_stylesheet('<link rel="stylesheet" href="' . $_skin_url . '/style.css?ver=' . G5_SERVER_TIME . '">', 0);
if (!function_exists('get_extension')) {
function get_extension($filename) {
$filename = basename($filename);
return substr(strrchr($filename, "."), 1);
}
}
// 💡 [핵심] 첨부파일 재구성: 썸네일(첫번째 파일)을 제외하고, 본문 이미지를 구성합니다.
$body_images = array();
if ($view['file']['count'] > 1) { // 썸네일(첫번째 파일)을 제외하고 2번째 파일부터 처리
$temp_files = $view['file'];
unset($temp_files['count']);
for ($i = 1; $i < $view['file']['count']; $i++) {
if (!isset($temp_files[$i])) continue;
$file = $temp_files[$i];
$ext = strtolower(get_extension($file['source']));
// 이미지 파일이면 본문 이미지 배열에 추가
if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif'])) {
$body_images[] = $file;
}
}
}
?>
<div id="coverage-board">
<!-- 💡 [추가] 관리자용 메인 노출 상태 표시 -->
<?php if ($is_admin && $view['wr_8'] == 'Y'): ?>
<div class="admin-option-item">
<span class="option-text">💡 이 글은 메인 화면 포트폴리오 영역에 노출되고 있습니다.</span>
</div>
<?php endif; ?>
<!-- 💡 [핵심] 본문 내용을 콘텐츠 타입에 따라 올바르게 출력합니다. -->
<div class="view-detail-content">
<?php
// 💡 [추가] 본문 내의 인라인 폰트 설정을 강제로 제거하는 함수
if (!function_exists('clean_font_styles')) {
function clean_font_styles($content) {
// style 속성 내의 font-family 항목을 제거 (정규식 사용)
return preg_replace('/font-family\s*:\s*[^;"]+;?/i', '', $content);
}
}
// HTML 에디터 사용 여부에 따라 conv_content 처리
$html = 0; // 기본값은 일반 텍스트
if (strstr($view['wr_option'], 'html1')) {
$html = 1;
} else if (strstr($view['wr_option'], 'html2')) {
$html = 2;
}
// 💡 [수정] HTML 태그가 포함되어 있으면 강제로 HTML 모드로 처리
if ($html == 0 && preg_match('/<[a-z][\s\S]*>/i', $view['wr_content'])) {
$html = 2; // HTML 태그가 발견되면 강제로 HTML2 모드 (모든 HTML 허용)
}
if ($html > 0) {
// 💡 [핵심] HTML 모드일 때는 원본 내용을 그대로 출력
// 이미지 경로 보정과 인라인 폰트 제거를 함께 적용합니다.
$processed_content = g5_dynamic_img_url($view['wr_content']);
echo clean_font_styles($processed_content);
} else {
// 일반 텍스트 모드일 때는 기존처럼 처리
echo nl2br(get_text($view['wr_content']));
}
?>
</div>
<?php if (!empty($body_images)): ?>
<div class="view-body-images">
<?php foreach ($body_images as $image): ?>
<figure class="body-image-item">
<img src="<?php echo $image['path'].'/'.$image['file']; ?>" alt="<?php echo $image['source']; ?>" data-full-src="<?php echo $image['path'].'/'.$image['file']; ?>">
<figcaption><?php echo $image['content']; ?></figcaption>
</figure>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<div class="view-footer">
<div class="btn-group-left">
<?php if ($prev_href): ?><a href="<?php echo $prev_href ?>" class="btn btn-secondary">이전글</a><?php endif; ?>
<?php if ($next_href): ?><a href="<?php echo $next_href ?>" class="btn btn-secondary">다음글</a><?php endif; ?>
</div>
<div class="btn-group-right">
<a href="<?php echo $list_href ?>" class="btn btn-primary">목록</a>
<?php if ($update_href): ?><a href="<?php echo $update_href ?>" class="btn btn-secondary">수정</a><?php endif; ?>
<?php if ($delete_href): ?><a href="<?php echo $delete_href ?>" onclick="del(this.href); return false;" class="btn btn-secondary">삭제</a><?php endif; ?>
<?php if ($write_href): ?><a href="<?php echo $write_href ?>" class="btn btn-primary">글쓰기</a><?php endif; ?>
</div>
</div>
<!-- 💡 [추가] 이미지 라이트박스 HTML 구조 -->
<div id="image-lightbox-popup" class="image-lightbox-popup">
<span class="lightbox-close-btn">&times;</span>
<img class="lightbox-content-img" id="lightbox-img-element">
<div class="lightbox-caption" id="lightbox-caption-element"></div>
</div>
<style>
/* 💡 [추가] 이미지 라이트박스 CSS */
.image-lightbox-popup {
display: none; /* 기본적으로 숨김 */
position: fixed; /* 화면 전체를 덮음 */
z-index: 10000; /* 다른 요소 위에 표시 */
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto; /* 이미지가 화면보다 클 경우 스크롤 */
background-color: rgba(0, 0, 0, 0.9); /* 반투명 검정 배경 */
justify-content: center;
align-items: center;
flex-direction: column;
}
.lightbox-content-img {
margin: auto;
display: block;
max-width: 90%;
max-height: 90%;
object-fit: contain; /* 이미지 비율 유지하며 컨테이너에 맞춤 */
border-radius: 8px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.7);
}
.lightbox-caption {
color: #ccc;
font-size: 1.2rem;
padding: 15px 20px;
text-align: center;
max-width: 90%;
margin-top: 10px;
}
.lightbox-close-btn {
position: absolute;
top: 20px;
right: 35px;
color: #fff;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
cursor: pointer;
}
.lightbox-close-btn:hover,
.lightbox-close-btn:focus {
color: #bbb;
text-decoration: none;
cursor: pointer;
}
/* 모바일 반응형 */
@media only screen and (max-width: 768px) {
.lightbox-content-img {
max-width: 95%;
max-height: 85%;
}
.lightbox-close-btn {
font-size: 30px;
top: 15px;
right: 25px;
}
.lightbox-caption {
font-size: 1rem;
padding: 10px 15px;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const lightbox = document.getElementById('image-lightbox-popup');
const lightboxImg = document.getElementById('lightbox-img-element');
const lightboxCaption = document.getElementById('lightbox-caption-element');
const closeBtn = document.querySelector('.lightbox-close-btn');
const bodyImagesContainer = document.querySelector('.view-body-images');
if (bodyImagesContainer) {
bodyImagesContainer.addEventListener('click', function(e) {
if (e.target.tagName === 'IMG') {
const imgSrc = e.target.getAttribute('data-full-src') || e.target.src;
const imgAlt = e.target.alt;
lightbox.style.display = 'flex';
lightboxImg.src = imgSrc;
lightboxCaption.textContent = imgAlt;
}
});
}
// 닫기 버튼 클릭 시 라이트박스 닫기
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';
}
});
}
// ESC 키 눌렀을 때 라이트박스 닫기
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && lightbox.style.display === 'flex') {
lightbox.style.display = 'none';
}
});
});
</script>