1
1
<script setup lang="ts">
2
2
import { ref , watch } from ' vue'
3
3
import { API } from ' ./net'
4
+ import type { Store } from ' ./store'
5
+ import type { Pair } from ' ./types'
4
6
import { ElMessage } from ' element-plus'
7
+ import { Codemirror } from ' vue-codemirror'
8
+ import HistoryInput from ' ../components/HistoryInput.vue'
5
9
6
- const stores = ref ([])
10
+ const stores = ref ([] as Store [] )
7
11
const kind = ref (' ' )
8
12
const store = ref (' ' )
9
13
const sqlQuery = ref (' ' )
10
- const queryResult = ref ([])
11
- const columns = ref ([])
14
+ const queryResult = ref ([] as any [])
15
+ const queryResultAsJSON= ref (' ' )
16
+ const columns = ref ([] as string [])
12
17
const queryTip = ref (' ' )
13
- const databases = ref ([])
14
- const tables = ref ([])
15
- const currentDatabase = ref (' ' )
16
18
const loadingStores = ref (true )
19
+ const dataFormat = ref (' table' )
20
+ const dataFormatOptions = [' table' , ' json' ]
21
+ const queryDataMeta = ref ({} as QueryDataMeta )
17
22
18
23
const tablesTree = ref ([])
19
24
watch (store , (s ) => {
@@ -24,12 +29,27 @@ watch(store, (s) => {
24
29
return
25
30
}
26
31
})
27
- currentDatabase . value = ' '
32
+ queryDataMeta . currentDatabase = ' '
28
33
sqlQuery .value = ' '
29
34
executeQuery ()
30
35
})
31
- const queryDataFromTable = (data ) => {
32
- sqlQuery .value = ` select * from ${data .label } limit 10 `
36
+
37
+ interface QueryDataMeta {
38
+ databases: string []
39
+ tables: string []
40
+ currentDatabase: string
41
+ duration: string
42
+ }
43
+
44
+ interface QueryData {
45
+ items: any []
46
+ data: any []
47
+ label: string
48
+ meta: QueryDataMeta
49
+ }
50
+
51
+ const queryDataFromTable = (data : QueryData ) => {
52
+ sqlQuery .value = ` select * from ${data .label } limit 100 `
33
53
executeQuery ()
34
54
}
35
55
const queryTables = () => {
@@ -61,43 +81,42 @@ API.GetStores((data) => {
61
81
loadingStores .value = false
62
82
})
63
83
64
- const ormDataHandler = (data ) => {
65
- const result = []
84
+ const ormDataHandler = (data : QueryData ) => {
85
+ const result = [] as any []
66
86
const cols = new Set ()
67
87
68
88
data .items .forEach (e => {
69
89
const obj = {}
70
- e .data .forEach (item => {
90
+ e .data .forEach (( item : Pair ) => {
71
91
obj [item .key ] = item .value
72
92
cols .add (item .key )
73
93
})
74
94
result .push (obj )
75
95
})
76
96
77
- databases .value = data .meta .databases
78
- tables .value = data .meta .tables
79
- currentDatabase .value = data .meta .currentDatabase
97
+ queryDataMeta .value = data .meta
80
98
queryResult .value = result
99
+ queryResultAsJSON .value = JSON .stringify (result , null , 2 )
81
100
columns .value = Array .from (cols ).sort ((a , b ) => {
82
101
if (a === ' id' ) return - 1 ;
83
102
if (b === ' id' ) return 1 ;
84
103
return a .localeCompare (b );
85
104
})
86
105
87
106
tablesTree .value = []
88
- tables .value .forEach ((i ) => {
107
+ queryDataMeta .value . tables .forEach ((i ) => {
89
108
tablesTree .value .push ({
90
109
label: i ,
91
110
})
92
111
})
93
112
}
94
113
95
- const keyValueDataHandler = (data ) => {
114
+ const keyValueDataHandler = (data : QueryData ) => {
96
115
queryResult .value = []
97
116
data .data .forEach (e => {
98
- const obj = {}
99
- obj [ ' key' ] = e .key
100
- obj [ ' value' ] = e .value
117
+ const obj = new Map < string , string >();
118
+ obj . set ( ' key' , e .key )
119
+ obj . set ( ' value' , e .value )
101
120
queryResult .value .push (obj )
102
121
103
122
columns .value = [' key' , ' value' ]
@@ -111,10 +130,13 @@ const executeQuery = async () => {
111
130
break ;
112
131
}
113
132
114
- API .DataQuery (store .value , kind .value , currentDatabase .value , sqlQuery .value , (data ) => {
133
+ let success = false
134
+ try {
135
+ const data = await API .DataQueryAsync (store .value , kind .value , queryDataMeta .value .currentDatabase , sqlQuery .value );
115
136
switch (kind .value ) {
116
137
case ' atest-store-orm' :
117
138
ormDataHandler (data )
139
+ success = true
118
140
break ;
119
141
case ' atest-store-etcd' :
120
142
keyValueDataHandler (data )
@@ -129,23 +151,24 @@ const executeQuery = async () => {
129
151
type: ' error'
130
152
});
131
153
}
132
- }, ( e ) => {
154
+ } catch ( e : any ) {
133
155
ElMessage ({
134
156
showClose: true ,
135
157
message: e .message ,
136
158
type: ' error'
137
159
});
138
- })
160
+ }
161
+ return success
139
162
}
140
163
</script >
141
164
142
165
<template >
143
166
<div >
144
- <el-container style =" height : calc (100vh - 45 px );" >
167
+ <el-container style =" height : calc (100vh - 50 px );" >
145
168
<el-aside v-if =" kind === 'atest-store-orm'" >
146
169
<el-scrollbar >
147
- <el-select v-model =" currentDatabase" placeholder =" Select database" @change =" queryTables" filterable >
148
- <el-option v-for =" item in databases" :key =" item" :label =" item"
170
+ <el-select v-model =" queryDataMeta. currentDatabase" placeholder =" Select database" @change =" queryTables" filterable >
171
+ <el-option v-for =" item in queryDataMeta. databases" :key =" item" :label =" item"
149
172
:value =" item" ></el-option >
150
173
</el-select >
151
174
<el-tree :data =" tablesTree" node-key =" label" @node-click =" queryDataFromTable" highlight-current draggable />
@@ -163,23 +186,34 @@ const executeQuery = async () => {
163
186
</el-select >
164
187
</el-form-item >
165
188
</el-col >
166
- <el-col :span =" 17 " >
189
+ <el-col :span =" 16 " >
167
190
<el-form-item >
168
- <el-input v-model = " sqlQuery " :placeholder = " queryTip " @keyup.enter = " executeQuery " ></ el-input >
191
+ <HistoryInput :placeholder = " queryTip " :callback = " executeQuery " v-model = " sqlQuery " / >
169
192
</el-form-item >
170
193
</el-col >
171
194
<el-col :span =" 2" >
172
195
<el-form-item >
173
196
<el-button type =" primary" @click =" executeQuery" >Execute</el-button >
174
197
</el-form-item >
175
198
</el-col >
199
+ <el-col :span =" 2" >
200
+ <el-select v-model =" dataFormat" placeholder =" Select data format" >
201
+ <el-option v-for =" item in dataFormatOptions" :key =" item" :label =" item" :value =" item" ></el-option >
202
+ </el-select >
203
+ </el-col >
176
204
</el-row >
177
205
</el-form >
178
206
</el-header >
179
207
<el-main >
180
- <el-table :data =" queryResult" >
181
- <el-table-column v-for =" col in columns" :key =" col" :prop =" col" :label =" col" ></el-table-column >
208
+ <div style =" display : flex ; gap : 8px ;" >
209
+ <el-tag type =" primary" v-if =" queryResult.length > 0" >{{ queryResult.length }} rows</el-tag >
210
+ <el-tag type =" primary" v-if =" queryDataMeta.duration" >{{ queryDataMeta.duration }}</el-tag >
211
+ </div >
212
+ <el-table :data =" queryResult" stripe v-if =" dataFormat === 'table'" >
213
+ <el-table-column v-for =" col in columns" :key =" col" :prop =" col" :label =" col" sortable />
182
214
</el-table >
215
+ <Codemirror v-else-if =" dataFormat === 'json'"
216
+ v-model =" queryResultAsJSON" />
183
217
</el-main >
184
218
</el-container >
185
219
</el-container >
0 commit comments