GNU/_PAGE/library/manual_ai/db_structure.php
<?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'; ?>