Skip to content

Commit 94dbf30

Browse files
committed
feat(sql): 查询构建器按 ER 图方式切换数据库(标题栏切换库+独立选库页)
1 parent 9876ab8 commit 94dbf30

3 files changed

Lines changed: 34 additions & 28 deletions

File tree

src/components/QueryBuilder.vue

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
<div class="flex items-center gap-2 text-sm font-medium text-gray-700 dark:text-gray-200">
1515
<Blocks class="w-4 h-4 text-gray-400"/>
1616
<span>{{ t('qb.title') }} · {{ activeLabel() }}</span>
17-
<span class="text-[11px] text-gray-400 font-normal">{{ t('qb.dragHint') }}</span>
17+
<span v-if="srcNoDb && pickedDb" class="text-[11px] text-gray-400 font-normal">/ {{ pickedDb }}</span>
18+
<button v-if="srcNoDb && pickedDb && !picking" class="text-[11px] text-blue-500 hover:underline cursor-pointer font-normal" @click="picking = true">{{ t('qb.switchDb') }}</button>
19+
<span v-else class="text-[11px] text-gray-400 font-normal">{{ t('qb.dragHint') }}</span>
1820
</div>
1921
<div class="flex items-center gap-2">
2022
<!-- 已存查询:载入 -->
@@ -51,14 +53,16 @@
5153

5254
<div v-if="loading" class="flex-1 flex items-center justify-center text-sm text-gray-400">{{ t('qb.loading') }}</div>
5355
<div v-else-if="error" class="flex-1 flex items-center justify-center text-sm text-red-500 px-6 text-center">{{ error }}</div>
54-
<!-- MySQL 连接未指定库:先选库 -->
55-
<div v-else-if="srcNoDb && !pickedDb" class="flex-1 flex flex-col items-center justify-center gap-3 text-sm text-gray-400 px-6 text-center">
56-
<span>{{ t('qb.pickDbFirst') }}</span>
57-
<select class="text-sm rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-1.5 focus:outline-none cursor-pointer min-w-[200px]"
58-
:value="''" @change="onPickDb($event)">
59-
<option value="" disabled>{{ t('qb.selectDb') }}</option>
60-
<option v-for="d in databases" :key="d" :value="d">{{ d }}</option>
61-
</select>
56+
<!-- MySQL 连接未指定库:选库页(首次或点“切换库”后) -->
57+
<div v-else-if="srcNoDb && (picking || !pickedDb)" class="flex-1 overflow-auto p-4">
58+
<div class="text-xs text-gray-500 dark:text-gray-400 mb-2">{{ t('qb.pickDbFirst') }}</div>
59+
<div v-if="databases.length" class="flex flex-wrap gap-2">
60+
<button v-for="d in databases" :key="d"
61+
class="px-3 py-1.5 text-xs rounded border cursor-pointer transition-colors"
62+
:class="d === pickedDb ? 'border-blue-400 text-blue-500 bg-blue-50 dark:bg-blue-900/20' : 'border-gray-300 dark:border-gray-600 hover:border-blue-400 hover:text-blue-500'"
63+
@click="selectDb(d)">{{ d }}</button>
64+
</div>
65+
<div v-else class="text-xs text-gray-400">{{ t('qb.noTables') }}</div>
6266
</div>
6367
<div v-else-if="tables.length === 0" class="flex-1 flex items-center justify-center text-sm text-gray-400 px-6 text-center">{{ t('qb.noTables') }}</div>
6468

@@ -91,12 +95,6 @@
9195
<div class="rounded border border-gray-200 dark:border-gray-700">
9296
<div class="px-2.5 py-1 text-[11px] font-medium text-gray-500">FROM / JOIN</div>
9397
<div class="px-2.5 pb-2 flex flex-col gap-1.5">
94-
<div v-if="srcNoDb" class="flex items-center gap-1.5">
95-
<span class="text-[11px] text-gray-400 w-10 flex-shrink-0">{{ t('qb.db') }}</span>
96-
<select :value="pickedDb" class="text-xs rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-2 py-1 focus:outline-none min-w-[160px]" @change="onPickDb($event)">
97-
<option v-for="d in databases" :key="d" :value="d">{{ d }}</option>
98-
</select>
99-
</div>
10098
<div class="flex items-center gap-1.5">
10199
<span class="text-[11px] text-gray-400 w-10 flex-shrink-0">FROM</span>
102100
<select v-model="table" class="text-xs rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-2 py-1 focus:outline-none min-w-[160px]">
@@ -351,6 +349,7 @@ const tables = ref<Tbl[]>([])
351349
const srcNoDb = ref(false)
352350
const databases = ref<string[]>([])
353351
const pickedDb = ref('')
352+
const picking = ref(false)
354353
355354
const table = ref('')
356355
const joins = ref<Join[]>([])
@@ -760,26 +759,30 @@ const load = async () => {
760759
}
761760
762761
// 选择/切换数据库:加载该库表并重置构建器
763-
const onPickDb = async (e: Event) => {
764-
const db = (e.target as HTMLSelectElement).value
765-
if (!db || db === pickedDb.value) {
762+
const selectDb = async (db: string) => {
763+
if (!db) {
766764
return
767765
}
766+
const switching = db !== pickedDb.value
768767
loading.value = true
769768
try {
770769
const source = resolveActiveSource()
771770
const list = await fetchTables(source, db)
772771
restoring = true
773772
pickedDb.value = db
774773
tables.value = list
775-
joins.value = []
776-
selectItems.value = []
777-
distinct.value = false
778-
groupBy.value = []
779-
wheres.value = []
780-
havings.value = []
781-
orders.value = []
782-
table.value = list[0]?.name || ''
774+
picking.value = false
775+
// 切到不同库才重置查询;重选同库则保持
776+
if (switching) {
777+
joins.value = []
778+
selectItems.value = []
779+
distinct.value = false
780+
groupBy.value = []
781+
wheres.value = []
782+
havings.value = []
783+
orders.value = []
784+
table.value = list[0]?.name || ''
785+
}
783786
await nextTick()
784787
restoring = false
785788
persist()
@@ -794,6 +797,7 @@ const onPickDb = async (e: Event) => {
794797
795798
const openBuilder = () => {
796799
visible.value = true
800+
picking.value = false
797801
load()
798802
}
799803

src/i18n/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1053,8 +1053,9 @@
10531053
"loading": "Loading schema…",
10541054
"noTables": "No tables in the current source",
10551055
"db": "Database",
1056-
"pickDbFirst": "This connection has no database selected — pick one first",
1056+
"pickDbFirst": "This connection has no database selected — pick one",
10571057
"selectDb": "Select a database…",
1058+
"switchDb": "Switch DB",
10581059
"tables": "Tables",
10591060
"columns": "Columns",
10601061
"value": "Value",

src/i18n/locales/zh-CN.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1053,8 +1053,9 @@
10531053
"loading": "加载表结构中…",
10541054
"noTables": "当前数据源没有可用的表",
10551055
"db": "数据库",
1056-
"pickDbFirst": "当前连接未指定数据库,请先选择一个数据库",
1056+
"pickDbFirst": "当前连接未指定数据库,请选择一个数据库",
10571057
"selectDb": "选择数据库…",
1058+
"switchDb": "切换库",
10581059
"tables": "",
10591060
"columns": "",
10601061
"value": "",

0 commit comments

Comments
 (0)