| <!DOCTYPE html> |
| <html lang="ja"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>DeepSeek DB インタラクティブアシスタント</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| .chat-container { |
| height: calc(100vh - 200px); |
| } |
| @media (max-width: 768px) { |
| .chat-container { |
| height: calc(100vh - 160px); |
| } |
| } |
| .typing-indicator::after { |
| content: '...'; |
| animation: typing 1.5s infinite; |
| } |
| @keyframes typing { |
| 0% { content: '.'; } |
| 33% { content: '..'; } |
| 66% { content: '...'; } |
| } |
| .fade-in { |
| animation: fadeIn 0.3s ease-in; |
| } |
| @keyframes fadeIn { |
| from { opacity: 0; transform: translateY(10px); } |
| to { opacity: 1; transform: translateY(0); } |
| } |
| </style> |
| </head> |
| <body class="bg-gray-100"> |
| <div class="container mx-auto px-4 py-8 max-w-6xl"> |
| |
| <header class="mb-8"> |
| <div class="flex items-center justify-between"> |
| <div class="flex items-center"> |
| <div class="w-12 h-12 bg-blue-600 rounded-full flex items-center justify-center mr-4"> |
| <i class="fas fa-database text-white text-xl"></i> |
| </div> |
| <div> |
| <h1 class="text-2xl font-bold text-gray-800">DeepSeek DB Assistant</h1> |
| <p class="text-gray-600">自然言語でデータベースを操作</p> |
| </div> |
| </div> |
| <div class="flex space-x-2"> |
| <button class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition flex items-center"> |
| <i class="fas fa-cog mr-2"></i>設定 |
| </button> |
| <button class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition flex items-center"> |
| <i class="fas fa-history mr-2"></i>履歴 |
| </button> |
| </div> |
| </div> |
| </header> |
|
|
| |
| <div class="bg-white rounded-xl shadow-lg overflow-hidden"> |
| <div class="p-4 border-b border-gray-200 bg-gray-50"> |
| <div class="flex items-center space-x-4"> |
| <div class="flex-1"> |
| <div class="flex space-x-2"> |
| <span class="px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-sm">MySQL</span> |
| <span class="px-3 py-1 bg-green-100 text-green-800 rounded-full text-sm">接続済み</span> |
| </div> |
| </div> |
| <div class="flex items-center space-x-2"> |
| <button id="new-chat-btn" class="px-3 py-1 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition flex items-center text-sm"> |
| <i class="fas fa-plus mr-1"></i>新しいチャット |
| </button> |
| <button class="p-2 text-gray-500 hover:text-gray-700 rounded-full hover:bg-gray-200 transition"> |
| <i class="fas fa-ellipsis-v"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="chat-container" class="chat-container overflow-y-auto p-4 space-y-4"> |
| |
| <div class="flex flex-col items-center justify-center py-12 text-center"> |
| <div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mb-4"> |
| <i class="fas fa-database text-blue-600 text-2xl"></i> |
| </div> |
| <h2 class="text-xl font-semibold text-gray-800 mb-2">DeepSeek DB Assistantへようこそ</h2> |
| <p class="text-gray-600 max-w-md">自然言語でデータベース操作を指示してください。SQLクエリの生成やデータ分析を支援します。</p> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-8 w-full max-w-2xl"> |
| <div class="bg-gray-50 p-4 rounded-lg cursor-pointer hover:bg-gray-100 transition border border-gray-200"> |
| <h3 class="font-medium text-gray-800 mb-2">「ユーザーーテーブルから東京在住のユーザーを抽出」</h3> |
| <p class="text-sm text-gray-500">条件に合致するデータを検索</p> |
| </div> |
| <div class="bg-gray-50 p-4 rounded-lg cursor-pointer hover:bg-gray-100 transition border border-gray-200"> |
| <h3 class="font-medium text-gray-800 mb-2">「売上データを月別に集計してグラフ表示」</h3> |
| <p class="text-sm text-gray-500">データの集計と可視化</p> |
| </div> |
| <div class="bg-gray-50 p-4 rounded-lg cursor-pointer hover:bg-gray-100 transition border border-gray-200"> |
| <h3 class="font-medium text-gray-800 mb-2">「新しい商品テーブルを作成」</h3> |
| <p class="text-sm text-gray-500">テーブル作成のSQL生成</p> |
| </div> |
| <div class="bg-gray-50 p-4 rounded-lg cursor-pointer hover:bg-gray-100 transition border border-gray-200"> |
| <h3 class="font-medium text-gray-800 mb-2">「注文テーブルと顧客テーブルを結合」</h3> |
| <p class="text-sm text-gray-500">複数テーブルの結合クエリ</p> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="p-4 border-t border-gray-200 bg-gray-50"> |
| <div class="relative"> |
| <textarea id="user-input" rows="1" class="w-full px-4 py-3 pr-12 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none" placeholder="データベースに何をしますか?例: ユーザーーテーブルから東京在住のユーザーを抽出"></textarea> |
| <button id="send-btn" class="absolute right-3 bottom-3 w-8 h-8 bg-blue-600 text-white rounded-full flex items-center justify-center hover:bg-blue-700 transition"> |
| <i class="fas fa-paper-plane"></i> |
| </button> |
| </div> |
| <div class="flex justify-between items-center mt-2 text-xs text-gray-500"> |
| <div> |
| <span class="hidden md:inline">DeepSeekモデルを使用しています</span> |
| <span class="inline md:hidden">DeepSeekモデル</span> |
| </div> |
| <div class="flex space-x-2"> |
| <button class="hover:text-gray-700"><i class="fas fa-microphone"></i></button> |
| <button class="hover:text-gray-700"><i class="fas fa-image"></i></button> |
| <input type="file" id="file-import" accept=".csv,.xlsx,.xls" class="hidden"> |
| <button id="import-btn" class="hover:text-gray-700"><i class="fas fa-file-import"></i></button> |
| <button id="edit-table-btn" class="hover:text-gray-700"><i class="fas fa-edit"></i></button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="data-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> |
| <div class="bg-white rounded-lg w-full max-w-4xl max-h-[90vh] overflow-hidden"> |
| <div class="flex justify-between items-center p-4 border-b"> |
| <h3 class="text-lg font-semibold" id="modal-title">データインポート</h3> |
| <button id="close-modal" class="text-gray-500 hover:text-gray-700"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="p-4 overflow-auto max-h-[80vh]" id="modal-content"> |
| |
| </div> |
| <div class="p-4 border-t flex justify-end space-x-2"> |
| <button id="cancel-btn" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300"> |
| キャンセル |
| </button> |
| <button id="confirm-btn" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"> |
| 適用 |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| // Modal elements |
| const dataModal = document.getElementById('data-modal'); |
| const modalTitle = document.getElementById('modal-title'); |
| const modalContent = document.getElementById('modal-content'); |
| const closeModal = document.getElementById('close-modal'); |
| const cancelBtn = document.getElementById('cancel-btn'); |
| const confirmBtn = document.getElementById('confirm-btn'); |
| const importBtn = document.getElementById('file-import'); |
| const editTableBtn = document.getElementById('edit-table-btn'); |
| |
| // Close modal handlers |
| function closeDataModal() { |
| dataModal.classList.add('hidden'); |
| } |
| |
| closeModal.addEventListener('click', closeDataModal); |
| cancelBtn.addEventListener('click', closeDataModal); |
| |
| // File import handler |
| document.getElementById('import-btn').addEventListener('click', function() { |
| importBtn.click(); |
| }); |
| |
| importBtn.addEventListener('change', function(e) { |
| const file = e.target.files[0]; |
| if (!file) return; |
| |
| const reader = new FileReader(); |
| reader.onload = function(e) { |
| modalTitle.textContent = 'データプレビュー (' + file.name + ')'; |
| modalContent.innerHTML = ` |
| <div class="mb-4"> |
| <h4 class="font-medium mb-2">インポート設定</h4> |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">先頭行をヘッダーとして使用</label> |
| <select class="w-full border rounded p-2"> |
| <option value="true">はい</option> |
| <option value="false">いいえ</option> |
| </select> |
| </div> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">テーブル名</label> |
| <input type="text" class="w-full border rounded p-2" placeholder="例: imported_data"> |
| </div> |
| </div> |
| </div> |
| <div class="overflow-auto"> |
| <h4 class="font-medium mb-2">データプレビュー</h4> |
| <div class="border rounded-lg overflow-hidden"> |
| <table class="min-w-full divide-y divide-gray-200"> |
| <thead class="bg-gray-50"> |
| <tr id="preview-head"></tr> |
| </thead> |
| <tbody class="bg-white divide-y divide-gray-200" id="preview-body"></tbody> |
| </table> |
| </div> |
| </div> |
| <div class="mt-4 p-4 bg-yellow-50 border-l-4 border-yellow-400"> |
| <div class="flex"> |
| <div class="flex-shrink-0"> |
| <svg class="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor"> |
| <path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" /> |
| </svg> |
| </div> |
| <div class="ml-3"> |
| <p class="text-sm text-yellow-700"> |
| この機能を使用するにはバックエンドAPIの実装が必要です。現在はプレビューのみ表示可能です。 |
| </p> |
| </div> |
| </div> |
| </div> |
| `; |
| |
| // Parse CSV/Excel and show preview |
| if (file.name.endsWith('.csv')) { |
| parseCSV(e.target.result); |
| } else if (file.name.endsWith('.xlsx') || file.name.endsWith('.xls')) { |
| parseExcel(e.target.result); |
| } |
| |
| dataModal.classList.remove('hidden'); |
| }; |
| |
| if (file.name.endsWith('.csv')) { |
| reader.readAsText(file); |
| } else { |
| reader.readAsArrayBuffer(file); |
| } |
| }); |
| |
| // Table editor handler |
| editTableBtn.addEventListener('click', function() { |
| modalTitle.textContent = 'テーブルエディター'; |
| modalContent.innerHTML = ` |
| <div class="mb-4"> |
| <div class="flex justify-between items-center mb-2"> |
| <h4 class="font-medium">テーブルを編集</h4> |
| <button id="add-row-btn" class="px-3 py-1 bg-blue-600 text-white rounded text-sm"> |
| <i class="fas fa-plus mr-1"></i>行を追加 |
| </button> |
| </div> |
| <div class="border rounded-lg overflow-hidden"> |
| <table class="min-w-full divide-y divide-gray-200"> |
| <thead class="bg-gray-50"> |
| <tr> |
| <th class="px-4 py-2 text-left">カラム名</th> |
| <th class="px-4 py-2 text-left">データ型</th> |
| <th class="px-4 py-2 text-left">操作</th> |
| </tr> |
| </thead> |
| <tbody class="bg-white divide-y divide-gray-200" id="edit-table-body"> |
| <tr> |
| <td class="px-4 py-2"><input type="text" class="border rounded p-1 w-full" value="id"></td> |
| <td class="px-4 py-2"> |
| <select class="border rounded p-1"> |
| <option>INT</option> |
| <option selected>VARCHAR</option> |
| <option>DATE</option> |
| <option>DECIMAL</option> |
| </select> |
| </td> |
| <td class="px-4 py-2"> |
| <button class="text-red-500 hover:text-red-700"> |
| <i class="fas fa-trash"></i> |
| </button> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| `; |
| |
| // Add row button handler |
| document.getElementById('add-row-btn').addEventListener('click', function() { |
| const tbody = document.getElementById('edit-table-body'); |
| const newRow = document.createElement('tr'); |
| newRow.innerHTML = ` |
| <td class="px-4 py-2"><input type="text" class="border rounded p-1 w-full" placeholder="カラム名"></td> |
| <td class="px-4 py-2"> |
| <select class="border rounded p-1"> |
| <option>INT</option> |
| <option selected>VARCHAR</option> |
| <option>DATE</option> |
| <option>DECIMAL</option> |
| </select> |
| </td> |
| <td class="px-4 py-2"> |
| <button class="text-red-500 hover:text-red-700"> |
| <i class="fas fa-trash"></i> |
| </button> |
| </td> |
| `; |
| tbody.appendChild(newRow); |
| }); |
| |
| dataModal.classList.remove('hidden'); |
| }); |
| |
| // CSV parsing function |
| function parseCSV(data) { |
| const rows = data.split('\n').slice(0, 10); // Show first 10 rows for preview |
| const header = rows[0].split(','); |
| const tbody = document.getElementById('preview-body'); |
| const thead = document.getElementById('preview-head'); |
| |
| // Create header |
| header.forEach(col => { |
| const th = document.createElement('th'); |
| th.textContent = col; |
| th.className = 'px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider'; |
| thead.appendChild(th); |
| }); |
| |
| // Create rows |
| rows.slice(1).forEach(row => { |
| const tr = document.createElement('tr'); |
| row.split(',').forEach(cell => { |
| const td = document.createElement('td'); |
| td.textContent = cell; |
| td.className = 'px-4 py-2 whitespace-nowrap text-sm text-gray-500'; |
| tr.appendChild(td); |
| }); |
| tbody.appendChild(tr); |
| }); |
| } |
| |
| // Excel parsing function (simplified - would need SheetJS in production) |
| function parseExcel(data) { |
| const warningDiv = document.createElement('div'); |
| warningDiv.className = 'mt-4 p-4 bg-yellow-50 border-l-4 border-yellow-400'; |
| warningDiv.innerHTML = ` |
| <div class="flex"> |
| <div class="flex-shrink-0"> |
| <svg class="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor"> |
| <path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" /> |
| </svg> |
| </div> |
| <div class="ml-3"> |
| <p class="text-sm text-yellow-700"> |
| Excelファイルのプレビュー機能は実装中です。完全な機能を使用するにはSheetJSライブラリとバックエンドAPIが必要です。 |
| </p> |
| </div> |
| </div> |
| `; |
| modalContent.appendChild(warningDiv); |
| } |
| const userInput = document.getElementById('user-input'); |
| const sendBtn = document.getElementById('send-btn'); |
| const chatContainer = document.getElementById('chat-container'); |
| const newChatBtn = document.getElementById('new-chat-btn'); |
| |
| // 入力欄の高さを自動調整 |
| userInput.addEventListener('input', function() { |
| this.style.height = 'auto'; |
| this.style.height = (this.scrollHeight) + 'px'; |
| }); |
| |
| // メッセージ送信処理 |
| function sendMessage() { |
| const message = userInput.value.trim(); |
| if (message === '') return; |
| |
| // ユーザーメッセージを表示 |
| addUserMessage(message); |
| userInput.value = ''; |
| userInput.style.height = 'auto'; |
| |
| // AIの応答をシシミュレート |
| simulateAIResponse(message); |
| } |
| |
| // ユーザーメッセージを追加 |
| function addUserMessage(message) { |
| const messageDiv = document.createElement('div'); |
| messageDiv.className = 'flex justify-end fade-in'; |
| messageDiv.innerHTML = ` |
| <div class="max-w-[80%]"> |
| <div class="bg-blue-600 text-white px-4 py-3 rounded-t-2xl rounded-l-2xl"> |
| ${message} |
| </div> |
| <div class="text-xs text-gray-500 mt-1 text-right">${new Date().toLocaleTimeString()}</div> |
| </div> |
| `; |
| chatContainer.appendChild(messageDiv); |
| chatContainer.scrollTop = chatContainer.scrollHeight; |
| } |
| |
| // AIメッセージを追加 |
| function addAIMessage(message, isTyping = false) { |
| const messageDiv = document.createElement('div'); |
| messageDiv.className = 'flex justify-start fade-in'; |
| |
| const typingClass = isTyping ? 'typing-indicator' : ''; |
| |
| messageDiv.innerHTML = ` |
| <div class="max-w-[80%]"> |
| <div class="flex items-start space-x-2"> |
| <div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center mt-1 flex-shrink-0"> |
| <i class="fas fa-database text-blue-600"></i> |
| </div> |
| <div class="bg-gray-100 text-gray-800 px-4 py-3 rounded-t-2xl rounded-r-2xl ${typingClass}"> |
| ${isTyping ? '' : message} |
| </div> |
| </div> |
| <div class="text-xs text-gray-500 mt-1 ml-10">${new Date().toLocaleTimeString()}</div> |
| </div> |
| `; |
| chatContainer.appendChild(messageDiv); |
| chatContainer.scrollTop = chatContainer.scrollHeight; |
| return messageDiv; |
| } |
| |
| // AIの応答をシシミュレート |
| function simulateAIResponse(userMessage) { |
| // タイピングインジケーターを表示 |
| const typingMessage = addAIMessage('', true); |
| |
| // 1-3秒のランダムな遅延を追加 |
| const delay = 1000 + Math.random() * 2000; |
| |
| setTimeout(() => { |
| // タイピングインジケーターを削除 |
| typingMessage.remove(); |
| |
| // 実際の応答を生成 |
| const response = generateAIResponse(userMessage); |
| addAIMessage(response); |
| }, delay); |
| } |
| |
| // ユーザーメッセージに基づいてAI応答を生成 |
| function generateAIResponse(userMessage) { |
| const lowerMessage = userMessage.toLowerCase(); |
| |
| if (lowerMessage.includes('抽出') || lowerMessage.includes('検索') || lowerMessage.includes('取得')) { |
| return `以下のSQLクエリを生成しました:\n\n<pre class="bg-gray-200 p-2 rounded text-sm overflow-x-auto">SELECT * FROM users WHERE address LIKE '%東京%';</pre>\n\nこのクエリを実行しますか?それとも修正が必要ですか?`; |
| } |
| else if (lowerMessage.includes('集計') || lowerMessage.includes('グラフ') || lowerMessage.includes('分析')) { |
| return `売上データの月別集計クエリとグラフを生成しました:\n\n<pre class="bg-gray-200 p-2 rounded text-sm overflow-x-auto">SELECT |
| DATE_FORMAT(order_date, '%Y-%m') AS month, |
| SUM(amount) AS total_sales |
| FROM orders |
| GROUP BY month |
| ORDER BY month;</pre>\n\n<svg viewBox="0 0 400 200" class="w-full h-auto mt-4 bg-white border border-gray-200 rounded p-2"> |
| |
| <rect x="50" y="50" width="30" height="120" fill="#3b82f6"/> |
| <rect x="100" y="80" width="30" height="90" fill="#3b82f6"/> |
| <rect x="150" y="30" width="30" height="140" fill="#3b82f6"/> |
| <rect x="200" y="60" width="30" height="110" fill="#3b82f6"/> |
| <rect x="250" y="90" width="30" height="80" fill="#3b82f6"/> |
| <rect x="300" y="120" width="30" height="50" fill="#3b82f6"/> |
| </svg>`; |
| } |
| else if (lowerMessage.includes('作成') || lowerMessage.includes('テーブル')) { |
| return `新しいテーブル作成用のSQLを生成しました:\n\n<pre class="bg-gray-200 p-2 rounded text-sm overflow-x-auto">CREATE TABLE products ( |
| id INT AUTO_INCREMENT PRIMARY KEY, |
| name VARCHAR(100) NOT NULL, |
| price DECIMAL(10,2) NOT NULL, |
| category VARCHAR(50), |
| stock_quantity INT DEFAULT 0, |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
| );</pre>\n\nこのテーブル定義で問題ありませんか?`; |
| } |
| else if (lowerMessage.includes('結合') || lowerMessage.includes('リレーション')) { |
| return `テーブル結合クエリを生成しました:\n\n<pre class="bg-gray-200 p-2 rounded text-sm overflow-x-auto">SELECT |
| o.order_id, |
| o.order_date, |
| c.customer_name, |
| c.email, |
| o.total_amount |
| FROM orders o |
| JOIN customers c ON o.customer_id = c.id |
| WHERE o.status = 'completed' |
| ORDER BY o.order_date DESC;</pre>\n\nさらに条件を追加したり、表示するカラムを変更できます。`; |
| } |
| else if (lowerMessage.includes('インポート') || lowerMessage.includes('取り込み') || lowerMessage.includes('csv') || lowerMessage.includes('excel')) { |
| return `データインポート機能を使用できます:\n\n1. 下部の📁アイコンをクリックしてCSV/Excelファイルを選択\n2. プレビューを確認後、インポートを実行\n3. インポートしたデータに対してクエリを実行可能\n\nまたは、以下のSQLで既存のファイルをインポートできます:\n\n<pre class="bg-gray-200 p-2 rounded text-sm overflow-x-auto">LOAD DATA INFILE 'data.csv' |
| INTO TABLE imported_data |
| FIELDS TERMINATED BY ',' |
| ENCLOSED BY '"' |
| LINES TERMINATED BY '\\n' |
| IGNORE 1 ROWS;</pre>`; |
| } |
| else if (lowerMessage.includes('編集') || lowerMessage.includes('変更') || lowerMessage.includes('テーブル定義')) { |
| return `テーブル構造を編集できます:\n\n1. 下部の✏️アイコンをクリックしてテーブルエディターを開く\n2. カラムの追加/削除やデータ型の変更が可能\n3. 変更を適用して新しいテーブル定義を生成\n\n生成されたSQL例:\n\n<pre class="bg-gray-200 p-2 rounded text-sm overflow-x-auto">ALTER TABLE products |
| ADD COLUMN description VARCHAR(255) AFTER price, |
| MODIFY COLUMN price DECIMAL(10,2) NOT NULL DEFAULT 0, |
| DROP COLUMN old_column;</pre>`; |
| } |
| else { |
| return `あなたのリクエスト「${userMessage}」を理解しました。DeepSeekモデルが適切なデータベース操作を分析しています。\n\n具体的にどのような操作を行いたいですか?例えば:\n\n- 特定の条件でデータを抽出\n- 複数テーブルの結合クエリ\n- データの集計と分析\n- 新しいテーブルの作成\n- データのインポート/エクスポート\n- テーブル構造の編集\n\nより詳細な情報を提供いただければ、最適なSQLクエリを生成できます。`; |
| } |
| } |
| |
| // イベントリスナー |
| sendBtn.addEventListener('click', sendMessage); |
| |
| userInput.addEventListener('keydown', function(e) { |
| if (e.key === 'Enter' && !e.shiftKey) { |
| e.preventDefault(); |
| sendMessage(); |
| } |
| }); |
| |
| newChatBtn.addEventListener('click', function() { |
| if (confirm('現在のチャットを終了して新しいチャットを開始しますか?')) { |
| chatContainer.innerHTML = ` |
| <div class="flex flex-col items-center justify-center py-12 text-center"> |
| <div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mb-4"> |
| <i class="fas fa-database text-blue-600 text-2xl"></i> |
| </div> |
| <h2 class="text-xl font-semibold text-gray-800 mb-2">新しいチャットを開始</h2> |
| <p class="text-gray-600 max-w-md">データベース操作について質問してください</p> |
| </div> |
| `; |
| } |
| }); |
| |
| // サンプルクエリのクリックイベント |
| const sampleQueries = document.querySelectorAll('.bg-gray-50'); |
| sampleQueries.forEach(query => { |
| query.addEventListener('click', function() { |
| const queryText = this.querySelector('h3').textContent; |
| userInput.value = queryText; |
| userInput.focus(); |
| }); |
| }); |
| }); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=kazuhina/dbinstraction" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |