<?php
require_once '/home/www/GNU/_PAGE/head.php';
/**
* @name Maria DB Table Master V1.3
* @desc 상세 용량 분석 + 다크 UI 동적 효과 + 관리 컬럼 슬림화 및 우측 배치
*/
error_reporting(E_ALL);
ini_set('display_errors', 1);
// 1. DB 연결 (로직 유지)
$ROOT = "/home/www";
$db_info_path = $ROOT . "/DB/db_upbit.php";
if (file_exists($db_info_path)) {
require_once $db_info_path;
}
if (!isset($db_upbit)) { exit("DB 연결 실패"); }
$pdo = $db_upbit;
// [로직] 테이블 설명 수정 처리 (로직 유지)
// 수정 후
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_table_comment') {
$tableName = $_POST['table_name'];
$newComment = $_POST['new_comment']; // 여기서 변수에 담고
$sql = "ALTER TABLE `$tableName` COMMENT ?";
$stmt = $pdo->prepare($sql);
// 이 부분이 26번 라인일 것입니다. $ 기호를 꼭 확인하세요!
$stmt->execute([$newComment]);
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
// 2. 스마트 볼륨 탐색 엔진 (로직 유지)
function get_smart_disk_info() {
exec('df -P', $output);
$oldboy = null; $maria = null;
foreach ($output as $line) {
if (preg_match('/^(\/\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)%\s+(\/.*)$/', $line, $m)) {
$path = $m[6];
$total_gb = round($m[2] / (1024 * 1024), 2);
$used_gb = round($m[3] / (1024 * 1024), 2);
$percent = $m[5];
if ($path === '/') {
$oldboy = ['label' => 'Oldboy (Root)', 'total' => $total_gb, 'used' => $used_gb, 'percent' => $percent, 'path' => '/'];
}
if ($total_gb > 150 && $total_gb < 250) {
$maria = ['label' => 'Maria (Storage)', 'total' => $total_gb, 'used' => $used_gb, 'percent' => $percent, 'path' => $path];
}
}
}
if (!$oldboy) $oldboy = ['label' => 'Oldboy', 'total' => 48.28, 'used' => 8.52, 'percent' => 17.6, 'path' => '/'];
if (!$maria) $maria = ['label' => 'Maria', 'total' => 200, 'used' => 0, 'percent' => 0, 'path' => 'Path Not Found'];
return [$oldboy, $maria];
}
$volumes = get_smart_disk_info();
// 3. 테이블 상세 정보 조회 (로직 유지)
$query = "
SELECT
TABLE_NAME,
TABLE_ROWS,
ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS TOTAL_MB,
ROUND(DATA_LENGTH / 1024 / 1024, 2) AS DATA_MB,
ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS INDEX_MB,
CREATE_TIME,
TABLE_COMMENT
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'upbit_data'
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC
";
$stmt = $pdo->query($query);
$tables = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<title>Maria DB Table Master v1.3 - Cyber Dark</title>
<link href="https://fonts.googleapis.com/css2?family=Pretendard:wght@300;450;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--bg: #0d1117;
--card: #161b22;
--border: #30363d;
--text: #e6edf3;
--accent: #58a6ff;
--neon-purple: #9d50bb;
--accent-glow: rgba(88, 166, 255, 0.4);
--purple-glow: rgba(157, 80, 187, 0.4);
}
/* 입장이미지 애니메이션 */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes growWidth { from { width: 0; } }
@keyframes pulseGlow {
0% { box-shadow: 0 0 5px var(--accent-glow); }
50% { box-shadow: 0 0 15px var(--accent-glow); }
100% { box-shadow: 0 0 5px var(--accent-glow); }
}
body {
font-family: 'Pretendard', sans-serif;
background: var(--bg);
color: var(--text);
margin: 0;
overflow-x: hidden;
}
.dictionary { padding:50px; }
/* 헤더 (로딩 효과) */
.header {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 30px; padding: 15px 25px;
background: var(--card); border-radius: 7px; border: 1px solid var(--border);
animation: fadeInUp 0.5s ease-out;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
}
h1 { color: #3ecbf6; font-size:30px; padding: 10px; }
h1 i { font-size:30px; padding: 10px; }
/* 디스크 그리드 */
.disk-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-bottom: 30px; }
.card {
background: var(--card); border-radius: 7px; padding: 22px;
border: 1px solid var(--border); border-left: 5px solid var(--accent);
transition: transform 0.3s, box-shadow 0.3s, border-color 0.3s;
animation: fadeInUp 0.7s ease-out both;
}
.card:hover { transform: translateY(-5px); border-color: var(--accent); box-shadow: 0 10px 25px rgba(0,0,0,0.5); }
.card.maria-vol { border-left-color: var(--neon-purple); }
.card.maria-vol:hover { border-color: var(--neon-purple); box-shadow: 0 10px 25px var(--purple-glow); }
/* 프로그레스 바 동적 효과 */
.progress-container { height: 10px; background: #30363d; border-radius: 5px; overflow: hidden; margin: 15px 0; }
.progress-fill {
height: 100%; border-radius: 5px;
animation: growWidth 1.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
box-shadow: 0 0 10px rgba(255,255,255,0.2);
}
/* 테이블 컨테이너 */
.table-container {
background: var(--card); border-radius: 7px; border: 1px solid var(--border);
overflow: hidden; animation: fadeInUp 0.9s ease-out both;
box-shadow: 0 10px 30px rgba(0,0,0,0.4);
}
table { width: 100%; border-collapse: collapse; table-layout: fixed; }
th { background: #21262d; padding: 16px; text-align: left; font-size: 0.8rem; color: #8b949e; text-transform: uppercase; letter-spacing: 0.5px; }
td { padding: 16px; border-bottom: 1px solid var(--border); font-size: 0.9rem; vertical-align: middle; transition: background 0.2s; }
/* 컬럼 폭 조정 및 정렬 */
.col-name { width: 18%; }
.col-rows { width: 10%; }
.col-size { width: 15%; }
.col-date { width: 12%; }
.col-comment { width: 37%; }
.col-action { width: 8%; text-align: right; } /* 폭 슬림화 & 우측 정렬 */
/* 배지 시스템 (로직 유지) */
.badge-base { display: inline-block; padding: 3px 10px; border-radius: 5px; font-weight: 700; font-size: 0.7rem; margin-right: 8px; }
.prefix-badge { background: rgba(88, 166, 255, 0.15); color: var(--accent); border: 1px solid rgba(88, 166, 255, 0.3); }
.suffix-badge { background: rgba(157, 80, 187, 0.15); color: #d3adf7; border: 1px solid rgba(157, 80, 187, 0.3); }
.row-count { font-weight: bold; color: var(--accent); font-family: 'Consolas', monospace; }
.size-badge { background: rgba(88, 166, 255, 0.1); color: var(--accent); padding: 4px 8px; border-radius: 6px; font-weight: bold; border: 1px solid rgba(88, 166, 255, 0.2); }
.btn-edit {
background: #21262d; border: 1px solid var(--border); color: var(--text);
padding: 8px 12px; border-radius: 7px; cursor: pointer; font-size: 0.75rem;
transition: all 0.3s; font-weight: 600;
}
.btn-edit:hover { background: var(--accent); color: #fff; border-color: var(--accent); box-shadow: 0 0 12px var(--accent-glow); }
code { color: #f6c23e; background: #0d1117; padding: 4px 8px; border-radius: 6px; font-family: 'Consolas', monospace; border: 1px solid var(--border); }
/* 행 애니메이션 및 호버 */
tbody tr { animation: fadeInUp 0.5s ease-out both; }
<?php for($i=1; $i<=20; $i++) { echo "tbody tr:nth-child($i) { animation-delay: ".(0.8 + ($i*0.04))."s; }"; } ?>
tr:hover td { background: rgba(88, 166, 255, 0.03); }
input#tableSearch {
padding: 12px 18px; border-radius: 7px; border: 1px solid var(--border);
background: #0d1117; color: #fff; width: 300px; outline: none; transition: 0.3s;
}
input#tableSearch:focus { border-color: var(--accent); box-shadow: 0 0 10px var(--accent-glow); }
/* 전체 스크롤바 스타일 */
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: #0d1117; }
::-webkit-scrollbar-thumb { background: #30363d; border-radius: 7px; border: 2px solid #0d1117; }
::-webkit-scrollbar-thumb:hover { background: #8b949e; }
</style>
<div class="dictionary">
<div class="header">
<h1><i class="fa-solid fa-database"></i> Maria DB Table Master <span style="font-size:0.8rem; color:var(--accent); margin-left:10px;">v1.3</span></h1>
<div style="display:flex; gap:15px; align-items:center;">
<div style="position:relative;">
<i class="fa-solid fa-magnifying-glass" style="position:absolute; left:12px; top:13px; color:#8b949e; font-size:0.9rem;"></i>
<input type="text" id="tableSearch" placeholder="Search tables..." style="padding-left:40px;">
</div>
<a href="?" class="btn-edit" style="font-size:0.9rem; padding:10px 18px;"><i class="fa-solid fa-sync"></i></a>
</div>
</div>
<div class="disk-grid">
<?php foreach ($volumes as $idx => $v): ?>
<div class="card <?php echo $idx == 1 ? 'maria-vol' : ''; ?>" style="animation-delay: <?php echo 0.2 + ($idx*0.2); ?>s;">
<div style="display:flex; justify-content:space-between; align-items:center;">
<div style="font-size:0.9rem; color:#8b949e; font-weight:bold;"><i class="fa-solid fa-hard-drive"></i> <?php echo $v['label']; ?></div>
<div style="font-size:0.85rem; color:var(--accent); font-weight:700;"><?php echo $v['percent']; ?>%</div>
</div>
<div style="font-size:1.8rem; font-weight:800; margin:12px 0;">
<?php echo $v['used']; ?> <small style="font-size:0.9rem; color:#8b949e;">GB</small>
<span style="color:var(--border); margin:0 5px;">/</span>
<?php echo $v['total']; ?> <small style="font-size:0.9rem; color:#8b949e;">GB</small>
</div>
<div class="progress-container">
<div class="progress-fill" style="width:<?php echo $v['percent']; ?>%; background:<?php echo $idx == 1 ? 'var(--neon-purple)' : 'var(--accent)'; ?>;"></div>
</div>
<div style="font-size: 0.75rem; color: #5a5f66; font-family: monospace;">Mount: <?php echo $v['path']; ?></div>
</div>
<?php endforeach; ?>
</div>
<div class="table-container">
<table id="targetTable">
<thead>
<tr>
<th class="col-name">Table Name</th>
<th class="col-rows">Rows</th>
<th class="col-size">Usage Details</th>
<th class="col-date">Created</th>
<th class="col-comment">Description</th>
<th class="col-action">Manage</th>
</tr>
</thead>
<tbody>
<?php foreach ($tables as $t): ?>
<tr>
<td><code><?php echo $t['TABLE_NAME']; ?></code></td>
<td class="row-count"><?php echo number_format($t['TABLE_ROWS']); ?></td>
<td>
<span class="size-badge"><?php echo $t['TOTAL_MB']; ?> <small>MB</small></span>
<div style="font-size:0.75rem; color:#8b949e; margin-top:6px; font-family:monospace;">
D: <?php echo $t['DATA_MB']; ?> / I: <?php echo $t['INDEX_MB']; ?>
</div>
</td>
<td style="color:#8b949e; font-size:0.85rem;"><?php echo date('Y.m.d', strtotime($t['CREATE_TIME'])); ?></td>
<td>
<?php
$comment = $t['TABLE_COMMENT'] ?: 'UNDEFINED_상세 설명 없음';
$parts = explode('_', $comment);
$count = count($parts);
if ($count >= 3) {
$prefix = array_shift($parts);
$suffix = array_pop($parts);
echo '<span class="badge-base prefix-badge">'.$prefix.'</span>';
echo '<span style="font-weight:500;">'.implode('_', $parts).'</span>';
echo '<span class="badge-base suffix-badge" style="margin-left:8px;">'.$suffix.'</span>';
} elseif ($count == 2) {
echo '<span class="badge-base prefix-badge">'.$parts[0].'</span>';
echo '<span>'.$parts[1].'</span>';
} else {
echo '<span>'.$comment.'</span>';
}
?>
</td>
<td class="col-action">
<button class="btn-edit" onclick="editTableComment('<?php echo $t['TABLE_NAME']; ?>', '<?php echo $t['TABLE_COMMENT']; ?>')">
<i class="fa-solid fa-pen-nib"></i> EDIT
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<form id="editForm" method="POST" style="display:none;">
<input type="hidden" name="action" value="update_table_comment">
<input type="hidden" name="table_name" id="formTableName">
<input type="hidden" name="new_comment" id="formNewComment">
</form>
<script>
// 테이블 설명 편집 (로직 유지)
function editTableComment(name, oldVal) {
const newVal = prompt(`[${name}] 테이블 설명 수정\n(분류_내용_태그 형식 추천):`, oldVal);
if (newVal !== null && newVal !== oldVal) {
document.getElementById('formTableName').value = name;
document.getElementById('formNewComment').value = newVal;
document.getElementById('editForm').submit();
}
}
// 실시간 검색 (로직 유지)
document.getElementById('tableSearch').addEventListener('input', function() {
const val = this.value.toLowerCase();
document.querySelectorAll('#targetTable tbody tr').forEach(row => {
row.style.display = row.innerText.toLowerCase().includes(val) ? '' : 'none';
});
});
console.log("Maria DB Cyber Master UI v1.3 Initialized.");
</script>
</div>
<?php require_once '/home/www/GNU/_PAGE/tail.php'; ?>