-
Notifications
You must be signed in to change notification settings - Fork 299
Expand file tree
/
Copy pathDatabase.vue
More file actions
142 lines (130 loc) · 4.71 KB
/
Database.vue
File metadata and controls
142 lines (130 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<script setup>
import { ref } from 'vue'
import { dbApi } from '../api/db'
const sqlQuery = ref('')
const queryResult = ref(null)
const loading = ref(false)
const error = ref(null)
// Example queries
const exampleQueries = [
{ name: '查看所有表', sql: "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;" },
{ name: '查看表结构', sql: "PRAGMA table_info(table_name);" },
{ name: '查询前10条记录', sql: "SELECT * FROM table_name LIMIT 10;" },
]
const executeQuery = async () => {
if (!sqlQuery.value.trim()) {
return
}
loading.value = true
error.value = null
queryResult.value = null
try {
const result = await dbApi.query(sqlQuery.value)
queryResult.value = result
} catch (e) {
error.value = e.message
} finally {
loading.value = false
}
}
const useExample = (sql) => {
sqlQuery.value = sql
}
</script>
<template>
<div class="space-y-6">
<!-- Header -->
<div>
<h2 class="text-xl font-semibold">数据库查询</h2>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">
执行只读 SQL 查询
</p>
</div>
<!-- Example queries -->
<div class="card p-4">
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">示例查询</h3>
<div class="flex flex-wrap gap-2">
<button
v-for="example in exampleQueries"
:key="example.name"
@click="useExample(example.sql)"
class="px-3 py-1.5 text-sm rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
>
{{ example.name }}
</button>
</div>
</div>
<!-- Query editor -->
<div class="card overflow-hidden">
<div class="p-4 border-b border-gray-200 dark:border-gray-700">
<textarea
v-model="sqlQuery"
placeholder="输入 SQL 查询语句..."
class="w-full min-h-[120px] p-3 bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg font-mono text-sm resize-none focus:outline-none focus:ring-2 focus:ring-primary-500"
spellcheck="false"
@keydown.ctrl.enter="executeQuery"
@keydown.meta.enter="executeQuery"
/>
<div class="flex items-center justify-between mt-3">
<span class="text-xs text-gray-500">
按 Ctrl+Enter 执行查询
</span>
<button
@click="executeQuery"
:disabled="loading || !sqlQuery.trim()"
class="btn btn-primary"
>
<svg v-if="loading" class="w-4 h-4 mr-2 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
执行查询
</button>
</div>
</div>
<!-- Error -->
<div v-if="error" class="p-4 bg-red-50 dark:bg-red-900/20 border-t border-red-200 dark:border-red-800">
<p class="text-red-600 dark:text-red-400 font-mono text-sm">{{ error }}</p>
</div>
<!-- Results -->
<div v-if="queryResult" class="overflow-x-auto">
<div v-if="Array.isArray(queryResult) && queryResult.length > 0" class="min-w-full">
<table class="w-full text-sm">
<thead class="bg-gray-50 dark:bg-gray-700/50">
<tr>
<th
v-for="column in Object.keys(queryResult[0])"
:key="column"
class="px-4 py-3 text-left font-medium text-gray-700 dark:text-gray-300 border-b border-gray-200 dark:border-gray-700"
>
{{ column }}
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
<tr
v-for="(row, index) in queryResult"
:key="index"
class="hover:bg-gray-50 dark:hover:bg-gray-700/30"
>
<td
v-for="column in Object.keys(queryResult[0])"
:key="column"
class="px-4 py-3 font-mono text-gray-900 dark:text-gray-100"
>
{{ row[column] }}
</td>
</tr>
</tbody>
</table>
</div>
<div v-else class="p-8 text-center text-gray-500">
查询成功,无结果返回
</div>
</div>
</div>
<!-- Result stats -->
<div v-if="queryResult && Array.isArray(queryResult)" class="text-sm text-gray-500 dark:text-gray-400">
查询返回 {{ queryResult.length }} 行结果
</div>
</div>
</template>