<?php
if (!defined('_GNUBOARD_')) exit;
// 상단 아이콘 및 폰트 추가 (원본 유지)
add_stylesheet('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">', 0);
add_stylesheet('<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Noto+Sans+KR:wght@300;400;500;700&family=JetBrains+Mono:wght@400;700&display=swap">', 0);
error_reporting(E_ALL & ~E_NOTICE);
ini_set('display_errors', '0');
// 데이터 로드 (원본 유지)
$new_board = sql_query("select * from $write_table order by wr_datetime desc limit 1");
$lat_board = sql_fetch_array($new_board);
?>
<style>
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css');
:root {
--neon-cyan: #00f2ff;
--neon-pink: #ff007a;
--neon-glow: rgba(0, 242, 255, 0.4);
--bg-black: #05060a;
--panel-bg: rgba(10, 15, 28, 0.85);
--border-color: rgba(0, 242, 255, 0.2);
--side-margin: 50px;
}
/* 시스템 로딩 애니메이션 */
#SYSTEM_INIT {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: var(--bg-black); z-index: 10000;
display: flex; flex-direction: column; align-items: center; justify-content: center;
transition: opacity 0.8s ease-in-out;
}
.init-text { font-family: 'Orbitron'; color: var(--neon-cyan); letter-spacing: 8px; font-size: 1.2rem; margin-bottom: 20px; }
.init-bar-wrap { width: 250px; height: 1px; background: rgba(255,255,255,0.1); overflow: hidden; }
.init-bar { width: 0%; height: 100%; background: var(--neon-cyan); box-shadow: 0 0 15px var(--neon-cyan); animation: initProgress 1.5s forwards ease-in-out; }
@keyframes initProgress { to { width: 100%; } }
/* 배경 및 레이아웃 */
#LIST_WRAP {
position: relative; min-height: 100vh; background: var(--bg-black);
padding: 60px 0; font-family: 'Pretendard', sans-serif; color: #fff;
background-image:
linear-gradient(rgba(0, 242, 255, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 242, 255, 0.05) 1px, transparent 1px);
background-size: 50px 50px;
animation: gridMove 20s linear infinite;
overflow-x: hidden;
}
@keyframes gridMove { from { background-position: 0 0; } to { background-position: 0 50px; } }
#starCanvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; opacity: 0.4; }
#LIST_CONTENT {
position: relative; z-index: 2;
width: calc(100% - 100px);
margin: 0 var(--side-margin);
}
/* 상단 헤더 */
.Header-Area {
display: flex; justify-content: space-between; align-items: flex-end;
padding-bottom: 25px; border-bottom: 2px solid var(--border-color);
margin-bottom: 40px;
}
.TopTitle { text-align: left; }
.TopTitle p {
font-family: 'Orbitron', sans-serif; font-size: 2.4rem; font-weight: 900;
margin: 0; color: #fff; letter-spacing: 2px; line-height: 1;
}
.TopTitle span {
display: inline-block; margin-top: 10px; font-size: 0.85rem;
color: var(--neon-cyan); letter-spacing: 3px; font-weight: 700; text-transform: uppercase;
}
.btn-cyber {
background: var(--neon-cyan); color: #000 !important;
font-family: 'Orbitron', sans-serif; font-weight: 900; border: none;
padding: 14px 35px; cursor: pointer;
clip-path: polygon(10% 0, 100% 0, 90% 100%, 0 100%);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
font-size: 0.9rem; letter-spacing: 1px;
}
.btn-cyber:hover { background: #fff; transform: scale(1.05) translateY(-3px); box-shadow: 0 0 30px var(--neon-cyan); }
/* 컨트롤 바 */
.Control-Bar {
display: flex; justify-content: space-between; align-items: center;
padding: 18px 25px; background: var(--panel-bg); border: 1px solid var(--border-color);
backdrop-filter: blur(15px); margin-bottom: 25px; border-radius: 4px;
}
.Filter-Group { display: flex; gap: 12px; flex-wrap: wrap; }
button, select {
background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.1);
color: var(--text-main); padding: 10px 15px; border-radius: 4px; cursor: pointer;
font-size: 0.85rem; transition: all 0.2s ease; outline: none; font-family: 'JetBrains Mono';
}
select option { background: #0a0e17; color: #fff; }
select:hover, button:not(.btn-cyber):hover { background: rgba(0, 242, 255, 0.1); border-color: var(--neon-cyan); }
/* 리스트 테이블 */
.List-Table { width: 100%; border-collapse: separate; border-spacing: 0 5px; }
.List-Table tr {
background: rgba(255, 255, 255, 0.02); transition: all 0.2s; cursor: pointer;
animation: slideIn 0.5s ease forwards; opacity: 0;
}
@keyframes slideIn { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } }
.List-Table tr:hover { background: rgba(0, 242, 255, 0.06); transform: scale(1.002) translateX(10px); }
.List-Table td { padding: 18px 15px; border-top: 1px solid rgba(255,255,255,0.03); border-bottom: 1px solid rgba(255,255,255,0.03); }
.List-Table td:first-child { border-left: 3px solid transparent; border-radius: 4px 0 0 4px; }
.List-Table tr:hover td:first-child { border-left-color: var(--neon-cyan); }
.List-Table td:last-child { border-radius: 0 4px 4px 0; }
.Num { width: 70px; text-align: center; color: var(--neon-cyan); font-size: 0.85rem; font-family: 'Orbitron'; font-weight: 700; opacity: 0.7; }
.Subject { font-size: 1.05rem; font-weight: 500; }
.Day { width: 220px; text-align: right; color: var(--text-dim); font-size: 0.85rem; font-family: 'JetBrains Mono'; }
/* 뱃지 */
.st_badge { display: inline-block; padding: 3px 12px; border-radius: 2px; font-size: 0.7rem; font-weight: 700; margin-right: 15px; text-transform: uppercase; border: 1px solid transparent; }
.st_blue { background: rgba(0, 242, 255, 0.1); color: var(--neon-cyan); border-color: rgba(0, 242, 255, 0.3); }
.st_purple { background: rgba(188, 0, 255, 0.1); color: #d689ff; border-color: rgba(188, 0, 255, 0.3); }
.st_green { background: rgba(0, 255, 122, 0.1); color: #4ade80; border-color: rgba(0, 255, 122, 0.3); }
/* 페이지네이션 디자인 (사이버 HUD 스타일로 변경) */
.Pagination {
text-align: center;
padding: 60px 0;
display: flex;
justify-content: center;
gap: 6px;
}
.Pagination a, .Pagination b, .Pagination span {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 40px;
height: 36px;
padding: 0 10px;
font-family: 'JetBrains Mono', monospace;
font-size: 0.9rem;
color: var(--text-dim);
text-decoration: none;
border: 1px solid var(--border-color);
background: rgba(255, 255, 255, 0.02);
clip-path: polygon(15% 0, 100% 0, 85% 100%, 0 100%); /* 사선 절단 효과 */
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.Pagination a:hover {
color: var(--neon-cyan);
border-color: var(--neon-cyan);
background: rgba(0, 242, 255, 0.1);
box-shadow: 0 0 10px var(--neon-glow);
transform: translateY(-3px);
}
.Pagination b {
background: var(--neon-cyan);
color: #000;
border-color: var(--neon-cyan);
font-weight: 900;
box-shadow: 0 0 15px var(--neon-glow);
}
@media (max-width: 1024px) {
:root { --side-margin: 20px; }
#LIST_CONTENT { width: calc(100% - 40px); margin: 0 20px; }
.Day { display: none; }
}
</style>
<!-- 시스템 초기화 화면 -->
<div id="SYSTEM_INIT">
<div class="init-text">ENCRYPTED_DATABASE_ACCESSING...</div>
<div class="init-bar-wrap">
<div class="init-bar"></div>
</div>
</div>
<div id="LIST_WRAP">
<canvas id="starCanvas"></canvas>
<article id='LIST_CONTENT'>
<section class="Header-Area">
<div class="TopTitle">
<p><?php echo strtoupper($bo_table); ?></p>
<span><i class="fa-solid fa-microchip"></i> <?php echo $board["bo_subject"]; ?></span>
</div>
<div class="Top-Action">
<?php if ($write_href) { ?>
<button type="button" onclick="location.href='<?php echo $write_href; ?>'" class="btn-cyber">NEW_DATABASE_ENTRY</button>
<?php } ?>
</div>
</section>
<div class="Control-Bar">
<div class="Filter-Group">
<button type="button" onclick="$('#NoticeLayer').fadeIn(200);"><i class="fa-solid fa-bullhorn"></i> NOTICE</button>
<?php if ($is_category) { ?>
<select onchange="location.href=this.value;">
<option value="<?php echo get_pretty_url($bo_table); ?>">CATEGORY</option>
<?php
$categories = explode('|', $board['bo_category_list']);
foreach($categories as $ca) {
if(!$ca) continue;
$selected = ($sca == $ca) ? "selected" : "";
echo "<option value='".get_pretty_url($bo_table, '', 'sca='.urlencode($ca))."' $selected>$ca</option>";
}
?>
</select>
<select onchange="location.href=this.value;">
<option value="<?php echo get_pretty_url($bo_table); ?>">FILTER_01</option>
<?php
$opts1 = explode('|', $board['bo_1']);
foreach($opts1 as $opt) {
if(!$opt) continue;
$selected = ($sfl == 'wr_1' && $stx == $opt) ? "selected" : "";
echo "<option value='".get_pretty_url($bo_table, '', 'sfl=wr_1&stx='.urlencode($opt))."' $selected>$opt</option>";
}
?>
</select>
<select onchange="location.href=this.value;">
<option value="<?php echo get_pretty_url($bo_table); ?>">FILTER_02</option>
<?php
$opts2 = explode('|', $board['bo_2']);
foreach($opts2 as $opt) {
if(!$opt) continue;
$selected = ($sfl == 'wr_2' && $stx == $opt) ? "selected" : "";
echo "<option value='".get_pretty_url($bo_table, '', 'sfl=wr_2&stx='.urlencode($opt))."' $selected>$opt</option>";
}
?>
</select>
<select onchange="location.href=this.value;">
<option value="<?php echo get_pretty_url($bo_table); ?>">FILTER_03</option>
<?php
$opts3 = explode('|', $board['bo_3']);
foreach($opts3 as $opt) {
if(!$opt) continue;
$selected = ($sfl == 'wr_3' && $stx == $opt) ? "selected" : "";
echo "<option value='".get_pretty_url($bo_table, '', 'sfl=wr_3&stx='.urlencode($opt))."' $selected>$opt</option>";
}
?>
</select>
<?php } ?>
</div>
<div class="Filter-Group">
<button type="button" onclick="$('#SCH').css('display','flex').hide().fadeIn(200);"><i class="fa-solid fa-search"></i> SEARCH</button>
<?php if ($is_admin) { ?>
<button type="button" onclick="location.href='<?php echo G5_ADMIN_URL; ?>/board_form.php?w=u&bo_table=<?php echo $bo_table; ?>'" style="color:var(--neon-pink);"><i class="fa-solid fa-cog"></i></button>
<?php } ?>
</div>
</div>
<form name="fboardlist" id="fboardlist" action="./board_list_update.php" method="post">
<input type="hidden" name="bo_table" value="<?php echo $bo_table; ?>">
<input type="hidden" name="sfl" value="<?php echo $sfl; ?>">
<input type="hidden" name="stx" value="<?php echo $stx; ?>">
<table class="List-Table">
<?php
for ($i=0; $i<count($list); $i++) {
$is_notice = $list[$i]['is_notice'];
$delay = ($i * 0.04);
$st_class = "st_blue";
if($list[$i]['x2_ca4'] == "완료") $st_class = "st_purple";
else if($list[$i]['x2_ca4'] == "대기") $st_class = "st_green";
?>
<tr onclick="location.href='<?php echo $list[$i]['href']; ?>'" style="animation-delay: <?php echo $delay; ?>s;">
<td class="Num">
<?php if ($is_notice) echo '<i class="fa-solid fa-thumbtack"></i>'; else echo $list[$i]['num']; ?>
</td>
<td class="Subject">
<?php
echo $list[$i]['icon_reply'];
if ($is_notice) echo "<span style='color:var(--neon-cyan); font-weight:700;'>".$list[$i]['subject']."</span>";
else echo $list[$i]['subject'];
if ($list[$i]['comment_cnt']) echo "<span style='color:var(--neon-pink); font-size:0.75rem; margin-left:10px; font-family:Orbitron;'>[".$list[$i]['comment_cnt']."]</span>";
?>
</td>
<td class="Day">
<?php if($list[$i]['x2_ca4']) { ?>
<span class="st_badge <?php echo $st_class; ?>"><?php echo $list[$i]['x2_ca4']; ?></span>
<?php } ?>
<span style="opacity:0.6;"><?php echo substr($list[$i]['wr_datetime'], 2, 8); ?></span>
</td>
</tr>
<?php } ?>
<?php if (count($list) == 0) echo "<tr><td colspan='3' style='text-align:center; padding:100px; color:var(--text-dim);'>NO DATA RETRIEVED.</td></tr>"; ?>
</table>
</form>
<div class="Pagination">
<?php echo $write_pages; ?>
</div>
<div id="NoticeLayer" style="display:none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 480px; background: #0a0e14; padding: 35px; border: 1px solid var(--neon-cyan); z-index: 10001; box-shadow: 0 0 50px rgba(0,0,0,0.9); backdrop-filter: blur(20px);">
<h3 style="margin-top:0; color:var(--neon-cyan); font-family:Orbitron; font-size:1.1rem; letter-spacing:2px; border-bottom:1px solid rgba(0,242,255,0.2); padding-bottom:15px;"><i class="fa-solid fa-info-circle"></i> SYSTEM_NOTICE</h3>
<div style="font-size:0.95rem; line-height:1.8; color:var(--text-main); max-height:300px; overflow-y:auto; margin:25px 0;">
<?php echo nl2br(stripslashes($board['notice'])); ?>
</div>
<div style="text-align:right;">
<button type="button" onclick="$('#NoticeLayer').fadeOut(200);" class="btn-cyber" style="padding:8px 25px; font-size:0.8rem;">ACKNOWLEDGE</button>
</div>
</div>
<section id="SCH" style="display:none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.85); z-index: 9999; align-items: center; justify-content: center;">
<div style="background:#0a0e14; padding:45px; border:1px solid var(--neon-cyan); width:90%; max-width:400px; box-shadow: 0 0 40px rgba(0,242,255,0.1);">
<form name="fsearch" method="get">
<input type="hidden" name="bo_table" value="<?php echo $bo_table; ?>">
<h3 style="margin:0 0 25px 0; color:var(--accent-cyan); font-size:0.9rem; font-family:'Orbitron'; letter-spacing:2px;">INTERNAL_SEARCH</h3>
<input type="text" name="stx" value="<?php echo stripslashes($stx); ?>" required placeholder="Keyword..." style="width:100%; background:rgba(255,255,255,0.05); border:none; border-bottom:2px solid var(--accent-cyan); color:#fff; font-size:1.2rem; outline:none; padding:10px 0; font-family: 'JetBrains Mono';">
<div style="margin-top:35px; display:flex; gap:12px;">
<button type="submit" class="btn-cyber" style="flex:1; height:45px; padding:0;">SEARCH</button>
<button type="button" onclick="$('#SCH').fadeOut(200);" style="flex:1; background:none; border:1px solid #444; color:#888;">CLOSE</button>
</div>
</form>
</div>
</section>
</article>
</div>
<script>
window.addEventListener('load', function() {
const loader = document.getElementById('SYSTEM_INIT');
setTimeout(() => {
loader.style.opacity = '0';
setTimeout(() => { loader.style.display = 'none'; }, 800);
}, 1200);
});
$(function() {
$('#SCH').click(function(e) { if(e.target == this) $(this).fadeOut(200); });
const canvas = document.getElementById('starCanvas');
const ctx = canvas.getContext('2d');
let stars = [];
function initStars() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
stars = [];
for(let i=0; i<100; i++) {
stars.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: Math.random() * 2,
opacity: Math.random() * 0.5
});
}
}
function drawStars() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#fff";
stars.forEach(s => {
ctx.globalAlpha = s.opacity;
ctx.beginPath();
ctx.arc(s.x, s.y, s.size, 0, Math.PI*2);
ctx.fill();
});
requestAnimationFrame(drawStars);
}
initStars();
drawStars();
window.addEventListener('resize', initStars);
});
</script>