<?php
/**
* Database Structure Viewer - AI Copy Final Fixed
* 수정사항: 전체 복사 시 텍스트 누락 오류 해결 및 사이버네틱 UI 적용
*/
$db_config_file = '/home/www/DB/db_upbit.php';
if (file_exists($db_config_file)) {
include_once($db_config_file);
} else {
die("설정 파일 로드 실패");
}
// 트리 생성 함수 (로직 유지)
function get_db_structure_with_comments($pdo) {
try {
$t_sql = "SELECT TABLE_NAME, TABLE_COMMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'upbit_data'";
$t_stmt = $pdo->query($t_sql);
$tables = $t_stmt->fetchAll();
foreach ($tables as $idx => $t_row) {
$table = $t_row['TABLE_NAME'];
$table_comment = $t_row['TABLE_COMMENT'];
$is_last_t = ($idx === count($tables) - 1);
$t_prefix = $is_last_t ? "└─ " : "├─ ";
$t_desc = $table_comment ? " /* {$table_comment} */" : "";
echo "<li class='tree-node'>";
echo " <div class='tree-line'>";
echo " <div class='tree-text'>{$t_prefix}TABLE: <span class='folder'>{$table}</span><span class='desc'>{$t_desc}</span></div>";
echo " <div class='copy-zone'><button class='copy-btn' onclick='copySubTree(this)'>복사</button></div>";
echo " </div>";
echo "<ul>";
$c_sql = "SELECT COLUMN_NAME, COLUMN_TYPE, COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'upbit_data' AND TABLE_NAME = '$table'
ORDER BY ORDINAL_POSITION";
$c_stmt = $pdo->query($c_sql);
$columns = $c_stmt->fetchAll();
foreach ($columns as $c_idx => $col) {
$is_last_c = ($c_idx === count($columns) - 1);
$c_indent = $is_last_t ? " " : "│ ";
$c_prefix = $is_last_c ? "└─ " : "├─ ";
$c_desc = $col['COLUMN_COMMENT'] ? " // {$col['COLUMN_COMMENT']}" : "";
echo "<li class='tree-node'>";
echo " <div class='tree-line'>";
echo " <div class='tree-text'>{$c_indent}{$c_prefix}<span class='file'>{$col['COLUMN_NAME']} ({$col['COLUMN_TYPE']})</span><span class='desc'>{$c_desc}</span></div>";
echo " <div class='copy-zone'><button class='copy-btn' onclick='copySubTree(this)'>복사</button></div>";
echo " </div>";
echo "</li>";
}
echo "</ul></li>";
}
} catch (Exception $e) { echo "Error: " . $e->getMessage(); }
}
?>
<?php require_once '/home/www/GNU/_PAGE/head.php'; ?>
<!-- 웹 폰트 및 아이콘 로드 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
/* [레이아웃 보정] 그누보드 충돌 방지 및 사이버네틱 디자인 */
#DB_MANUAL_WRAP {
background-color: #050505;
background-image: radial-gradient(circle at 50% 50%, #1a1f35 0%, #050505 100%);
color: #e0e0e0;
font-family: 'Inter', sans-serif;
padding: 40px 0;
min-height: 800px;
display: flex;
justify-content: center;
}
.db-container {
width: calc(100% - 40px);
max-width: 1300px;
border: 1px solid #222;
padding: 30px;
background-color: rgba(15, 15, 20, 0.95);
border-radius: 16px;
box-shadow: 0 25px 50px rgba(0,0,0,0.6);
backdrop-filter: blur(15px);
position: relative;
overflow: hidden;
}
/* 헤더 영역 */
.db-header-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #333;
padding-bottom: 20px;
margin-bottom: 30px;
}
.db-header {
color: #00ff88;
font-family: 'JetBrains Mono', monospace;
font-size: 1.4rem;
font-weight: bold;
margin: 0;
display: flex;
align-items: center;
gap: 15px;
letter-spacing: 1px;
}
/* 전체 복사 버튼 */
.copy-all-btn {
background-color: #00ff88;
color: #000;
border: none;
padding: 10px 20px;
font-family: 'JetBrains Mono', monospace;
font-weight: 900;
font-size: 12px;
cursor: pointer;
border-radius: 6px;
transition: all 0.3s;
text-transform: uppercase;
}
.copy-all-btn:hover {
background-color: #fff;
box-shadow: 0 0 20px rgba(0, 255, 136, 0.5);
transform: translateY(-2px);
}
/* 트리 구조 디자인 */
ul { list-style: none; padding: 0; margin: 0; }
.tree-line {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid rgba(255,255,255,0.02);
padding: 6px 12px;
transition: 0.2s;
border-radius: 6px;
}
.tree-line:hover {
background-color: rgba(255, 255, 255, 0.05);
box-shadow: inset 0 0 15px rgba(0, 210, 255, 0.05);
}
.tree-text {
font-family: 'JetBrains Mono', monospace;
white-space: pre;
flex-grow: 1;
font-size: 13px;
color: #d1d1d1;
}
/* 개별 요소 색상 */
.folder { color: #f1c40f; font-weight: bold; } /* TABLE */
.file { color: #00d2ff; } /* COLUMN */
.desc { color: #00ff88; font-weight: bold; opacity: 0.8; margin-left: 10px; } /* COMMENT */
/* 복사 버튼 사이버 스타일 */
.copy-btn {
background-color: transparent;
color: #666;
border: 1px solid #333;
padding: 4px 12px;
font-size: 10px;
font-family: 'JetBrains Mono', monospace;
cursor: pointer;
border-radius: 4px;
font-weight: bold;
transition: all 0.3s;
}
.copy-btn:hover {
background-color: #00ff88;
color: #000;
border-color: #00ff88;
box-shadow: 0 0 15px rgba(0, 255, 136, 0.4);
}
/* 스크롤바 커스텀 */
#DB_MANUAL_WRAP ::-webkit-scrollbar { width: 8px; }
#DB_MANUAL_WRAP ::-webkit-scrollbar-track { background: #0a0a0a; }
#DB_MANUAL_WRAP ::-webkit-scrollbar-thumb { background: #222; border-radius: 4px; }
</style>
<div id="DB_MANUAL_WRAP">
<div class="db-container">
<div class="db-header-wrapper">
<h1 class="db-header"><i class="fa-solid fa-database"></i> DATABASE_SCHEMA: upbit_data</h1>
<button class="copy-all-btn" onclick="copyAllStructure()"><i class="fa-solid fa-copy"></i> DB 구조 전체 복사</button>
</div>
<ul>
<?php get_db_structure_with_comments($db_upbit); ?>
</ul>
</div>
</div>
<script>
/**
* [로직 유지] 클립보드 복사 유틸리티
*/
function doCopy(text) {
const temp = document.createElement("textarea");
temp.value = text;
document.body.appendChild(temp);
temp.select();
document.execCommand('copy');
document.body.removeChild(temp);
}
/**
* [로직 유지] 하위 노드 포함 텍스트 복사
*/
function copySubTree(btn) {
const parentNode = btn.closest('.tree-node');
const allTexts = Array.from(parentNode.querySelectorAll('.tree-text'))
.map(el => el.innerText)
.join('\n');
doCopy(allTexts);
const originalText = btn.innerText;
btn.innerText = "SUCCESS";
btn.style.backgroundColor = "#00ff88";
btn.style.color = "#000";
setTimeout(() => {
btn.innerText = originalText;
btn.style.backgroundColor = "";
btn.style.color = "";
}, 1000);
}
/**
* [로직 유지] 전체 구조 텍스트 복사
*/
function copyAllStructure() {
const nodes = document.querySelectorAll('.tree-text');
const allText = Array.from(nodes).map(el => el.innerText).join('\n');
doCopy("DATABASE: upbit_data\n" + allText);
const btn = document.querySelector('.copy-all-btn');
const originalText = btn.innerHTML;
btn.innerHTML = "<i class='fa-solid fa-check'></i> 전체 복사 성공!";
setTimeout(() => {
btn.innerHTML = originalText;
}, 1500);
}
</script>
<?php require_once '/home/www/GNU/_PAGE/tail.php'; ?>