fdb2 1.0.13 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/README.md +9 -2
  2. package/bin/docker/.env +4 -0
  3. package/package.json +26 -18
  4. package/public/favicon.ico +0 -0
  5. package/public/favicon.png +0 -0
  6. package/view/modules/header.tpl +1 -1
  7. package/.dockerignore +0 -21
  8. package/.editorconfig +0 -11
  9. package/.eslintrc.cjs +0 -14
  10. package/.eslintrc.json +0 -7
  11. package/.prettierrc.js +0 -3
  12. package/.tpl.env +0 -22
  13. package/.vscodeignore +0 -45
  14. package/dist/package.json +0 -115
  15. package/dist/pnpm-lock.yaml +0 -8135
  16. package/dist/public/.vite/manifest.json +0 -82
  17. package/dist/public/bootstrap-icons.woff +0 -0
  18. package/dist/public/bootstrap-icons.woff2 +0 -0
  19. package/dist/public/bootstrap.css +0 -14152
  20. package/dist/public/bootstrap.js +0 -5038
  21. package/dist/public/explorer.css +0 -2379
  22. package/dist/public/explorer.js +0 -50586
  23. package/dist/public/index.css +0 -1099
  24. package/dist/public/index.js +0 -12862
  25. package/dist/public/layout.css +0 -318
  26. package/dist/public/layout.js +0 -25
  27. package/dist/public/vue.css +0 -1
  28. package/dist/public/vue.js +0 -9110
  29. package/dist/scripts/preinstall.js +0 -112
  30. package/dist/server/index.d.ts +0 -2
  31. package/dist/server/index.d.ts.map +0 -1
  32. package/dist/server/index.js +0 -601
  33. package/dist/server/index.js.map +0 -1
  34. package/dist/server/index.ts +0 -681
  35. package/dist/server/model/connection.entity.d.ts +0 -55
  36. package/dist/server/model/connection.entity.d.ts.map +0 -1
  37. package/dist/server/model/connection.entity.js +0 -59
  38. package/dist/server/model/connection.entity.js.map +0 -1
  39. package/dist/server/model/connection.entity.ts +0 -66
  40. package/dist/server/model/database.entity.d.ts +0 -203
  41. package/dist/server/model/database.entity.d.ts.map +0 -1
  42. package/dist/server/model/database.entity.js +0 -211
  43. package/dist/server/model/database.entity.js.map +0 -1
  44. package/dist/server/model/database.entity.ts +0 -246
  45. package/dist/server/service/connection.service.d.ts +0 -84
  46. package/dist/server/service/connection.service.d.ts.map +0 -1
  47. package/dist/server/service/connection.service.js +0 -369
  48. package/dist/server/service/connection.service.js.map +0 -1
  49. package/dist/server/service/connection.service.ts +0 -359
  50. package/dist/server/service/database/base.service.d.ts +0 -183
  51. package/dist/server/service/database/base.service.d.ts.map +0 -1
  52. package/dist/server/service/database/base.service.js +0 -253
  53. package/dist/server/service/database/base.service.js.map +0 -1
  54. package/dist/server/service/database/base.service.ts +0 -407
  55. package/dist/server/service/database/cockroachdb.service.d.ts +0 -116
  56. package/dist/server/service/database/cockroachdb.service.d.ts.map +0 -1
  57. package/dist/server/service/database/cockroachdb.service.js +0 -812
  58. package/dist/server/service/database/cockroachdb.service.js.map +0 -1
  59. package/dist/server/service/database/cockroachdb.service.ts +0 -871
  60. package/dist/server/service/database/database.service.d.ts +0 -495
  61. package/dist/server/service/database/database.service.d.ts.map +0 -1
  62. package/dist/server/service/database/database.service.js +0 -711
  63. package/dist/server/service/database/database.service.js.map +0 -1
  64. package/dist/server/service/database/database.service.ts +0 -776
  65. package/dist/server/service/database/index.d.ts +0 -8
  66. package/dist/server/service/database/index.d.ts.map +0 -1
  67. package/dist/server/service/database/index.js +0 -18
  68. package/dist/server/service/database/index.js.map +0 -1
  69. package/dist/server/service/database/index.ts +0 -7
  70. package/dist/server/service/database/mongodb.service.d.ts +0 -121
  71. package/dist/server/service/database/mongodb.service.d.ts.map +0 -1
  72. package/dist/server/service/database/mongodb.service.js +0 -502
  73. package/dist/server/service/database/mongodb.service.js.map +0 -1
  74. package/dist/server/service/database/mongodb.service.ts +0 -501
  75. package/dist/server/service/database/mssql.service.d.ts +0 -118
  76. package/dist/server/service/database/mssql.service.d.ts.map +0 -1
  77. package/dist/server/service/database/mssql.service.js +0 -871
  78. package/dist/server/service/database/mssql.service.js.map +0 -1
  79. package/dist/server/service/database/mssql.service.ts +0 -932
  80. package/dist/server/service/database/mysql.service.d.ts +0 -114
  81. package/dist/server/service/database/mysql.service.d.ts.map +0 -1
  82. package/dist/server/service/database/mysql.service.js +0 -960
  83. package/dist/server/service/database/mysql.service.js.map +0 -1
  84. package/dist/server/service/database/mysql.service.ts +0 -1026
  85. package/dist/server/service/database/oracle.service.d.ts +0 -126
  86. package/dist/server/service/database/oracle.service.d.ts.map +0 -1
  87. package/dist/server/service/database/oracle.service.js +0 -963
  88. package/dist/server/service/database/oracle.service.js.map +0 -1
  89. package/dist/server/service/database/oracle.service.ts +0 -1036
  90. package/dist/server/service/database/postgres.service.d.ts +0 -122
  91. package/dist/server/service/database/postgres.service.d.ts.map +0 -1
  92. package/dist/server/service/database/postgres.service.js +0 -882
  93. package/dist/server/service/database/postgres.service.js.map +0 -1
  94. package/dist/server/service/database/postgres.service.ts +0 -961
  95. package/dist/server/service/database/sap.service.d.ts +0 -115
  96. package/dist/server/service/database/sap.service.d.ts.map +0 -1
  97. package/dist/server/service/database/sap.service.js +0 -868
  98. package/dist/server/service/database/sap.service.js.map +0 -1
  99. package/dist/server/service/database/sap.service.ts +0 -922
  100. package/dist/server/service/database/sqlite.service.d.ts +0 -112
  101. package/dist/server/service/database/sqlite.service.d.ts.map +0 -1
  102. package/dist/server/service/database/sqlite.service.js +0 -723
  103. package/dist/server/service/database/sqlite.service.js.map +0 -1
  104. package/dist/server/service/database/sqlite.service.ts +0 -787
  105. package/dist/server/service/session.service.ts +0 -158
  106. package/dist/view/index.html +0 -45
  107. package/env.d.ts +0 -1
  108. package/packages/vscode/.vscodeignore +0 -44
  109. package/packages/vscode/README.md +0 -62
  110. package/packages/vscode/out/database-services/base.service.js +0 -236
  111. package/packages/vscode/out/database-services/base.service.js.map +0 -1
  112. package/packages/vscode/out/database-services/cockroachdb.service.js +0 -634
  113. package/packages/vscode/out/database-services/cockroachdb.service.js.map +0 -1
  114. package/packages/vscode/out/database-services/connection.service.js +0 -346
  115. package/packages/vscode/out/database-services/connection.service.js.map +0 -1
  116. package/packages/vscode/out/database-services/database.service.js +0 -571
  117. package/packages/vscode/out/database-services/database.service.js.map +0 -1
  118. package/packages/vscode/out/database-services/index.js +0 -18
  119. package/packages/vscode/out/database-services/index.js.map +0 -1
  120. package/packages/vscode/out/database-services/model/connection.entity.js +0 -11
  121. package/packages/vscode/out/database-services/model/connection.entity.js.map +0 -1
  122. package/packages/vscode/out/database-services/model/database.entity.js +0 -35
  123. package/packages/vscode/out/database-services/model/database.entity.js.map +0 -1
  124. package/packages/vscode/out/database-services/mongodb.service.js +0 -458
  125. package/packages/vscode/out/database-services/mongodb.service.js.map +0 -1
  126. package/packages/vscode/out/database-services/mssql.service.js +0 -694
  127. package/packages/vscode/out/database-services/mssql.service.js.map +0 -1
  128. package/packages/vscode/out/database-services/mysql.service.js +0 -735
  129. package/packages/vscode/out/database-services/mysql.service.js.map +0 -1
  130. package/packages/vscode/out/database-services/oracle.service.js +0 -787
  131. package/packages/vscode/out/database-services/oracle.service.js.map +0 -1
  132. package/packages/vscode/out/database-services/postgres.service.js +0 -696
  133. package/packages/vscode/out/database-services/postgres.service.js.map +0 -1
  134. package/packages/vscode/out/database-services/sap.service.js +0 -695
  135. package/packages/vscode/out/database-services/sap.service.js.map +0 -1
  136. package/packages/vscode/out/database-services/sqlite.service.js +0 -532
  137. package/packages/vscode/out/database-services/sqlite.service.js.map +0 -1
  138. package/packages/vscode/out/extension.js +0 -93
  139. package/packages/vscode/out/extension.js.map +0 -1
  140. package/packages/vscode/out/provider/DatabaseTreeProvider.js +0 -159
  141. package/packages/vscode/out/provider/DatabaseTreeProvider.js.map +0 -1
  142. package/packages/vscode/out/provider/WebViewProvider.js +0 -259
  143. package/packages/vscode/out/provider/WebViewProvider.js.map +0 -1
  144. package/packages/vscode/out/service/ConnectionManager.js +0 -105
  145. package/packages/vscode/out/service/ConnectionManager.js.map +0 -1
  146. package/packages/vscode/out/service/DatabaseServiceBridge.js +0 -395
  147. package/packages/vscode/out/service/DatabaseServiceBridge.js.map +0 -1
  148. package/packages/vscode/out/typings/connection.js +0 -3
  149. package/packages/vscode/out/typings/connection.js.map +0 -1
  150. package/packages/vscode/package.json +0 -144
  151. package/packages/vscode/resources/icon.svg +0 -5
  152. package/packages/vscode/resources/webview/_plugin-vue_export-helper.js +0 -6529
  153. package/packages/vscode/resources/webview/_plugin-vue_export-helper.js.map +0 -1
  154. package/packages/vscode/resources/webview/connection.css +0 -69
  155. package/packages/vscode/resources/webview/connection.js +0 -228
  156. package/packages/vscode/resources/webview/connection.js.map +0 -1
  157. package/packages/vscode/resources/webview/database.css +0 -259
  158. package/packages/vscode/resources/webview/database.js +0 -275
  159. package/packages/vscode/resources/webview/database.js.map +0 -1
  160. package/packages/vscode/resources/webview/favicon.ico +0 -0
  161. package/packages/vscode/resources/webview/index.html +0 -9
  162. package/packages/vscode/resources/webview/modules/header.tpl +0 -14
  163. package/packages/vscode/resources/webview/modules/initial_state.tpl +0 -55
  164. package/packages/vscode/resources/webview/query.css +0 -162
  165. package/packages/vscode/resources/webview/query.js +0 -198
  166. package/packages/vscode/resources/webview/query.js.map +0 -1
  167. package/packages/vscode/src/database-services/base.service.js.map +0 -1
  168. package/packages/vscode/src/database-services/base.service.ts +0 -363
  169. package/packages/vscode/src/database-services/cockroachdb.service.js.map +0 -1
  170. package/packages/vscode/src/database-services/cockroachdb.service.ts +0 -659
  171. package/packages/vscode/src/database-services/connection.service.ts +0 -341
  172. package/packages/vscode/src/database-services/database.service.ts +0 -630
  173. package/packages/vscode/src/database-services/index.ts +0 -7
  174. package/packages/vscode/src/database-services/model/connection.entity.js +0 -11
  175. package/packages/vscode/src/database-services/model/connection.entity.js.map +0 -1
  176. package/packages/vscode/src/database-services/model/connection.entity.ts +0 -66
  177. package/packages/vscode/src/database-services/model/database.entity.js +0 -35
  178. package/packages/vscode/src/database-services/model/database.entity.js.map +0 -1
  179. package/packages/vscode/src/database-services/model/database.entity.ts +0 -246
  180. package/packages/vscode/src/database-services/mongodb.service.js.map +0 -1
  181. package/packages/vscode/src/database-services/mongodb.service.ts +0 -454
  182. package/packages/vscode/src/database-services/mssql.service.js.map +0 -1
  183. package/packages/vscode/src/database-services/mssql.service.ts +0 -723
  184. package/packages/vscode/src/database-services/mysql.service.js.map +0 -1
  185. package/packages/vscode/src/database-services/mysql.service.ts +0 -761
  186. package/packages/vscode/src/database-services/oracle.service.js.map +0 -1
  187. package/packages/vscode/src/database-services/oracle.service.ts +0 -832
  188. package/packages/vscode/src/database-services/postgres.service.js.map +0 -1
  189. package/packages/vscode/src/database-services/postgres.service.ts +0 -741
  190. package/packages/vscode/src/database-services/sap.service.js.map +0 -1
  191. package/packages/vscode/src/database-services/sap.service.ts +0 -713
  192. package/packages/vscode/src/database-services/sqlite.service.js.map +0 -1
  193. package/packages/vscode/src/database-services/sqlite.service.ts +0 -558
  194. package/packages/vscode/src/extension.ts +0 -76
  195. package/packages/vscode/src/provider/DatabaseTreeProvider.ts +0 -167
  196. package/packages/vscode/src/provider/WebViewProvider.ts +0 -277
  197. package/packages/vscode/src/service/DatabaseServiceBridge.ts +0 -414
  198. package/packages/vscode/src/typings/connection.ts +0 -90
  199. package/packages/vscode/tsconfig.json +0 -21
  200. package/scripts/preinstall.js +0 -112
  201. package/server/index.ts +0 -681
  202. package/server/model/connection.entity.js +0 -11
  203. package/server/model/connection.entity.js.map +0 -1
  204. package/server/model/connection.entity.ts +0 -66
  205. package/server/model/database.entity.js +0 -35
  206. package/server/model/database.entity.js.map +0 -1
  207. package/server/model/database.entity.ts +0 -246
  208. package/server/service/connection.service.ts +0 -359
  209. package/server/service/database/base.service.ts +0 -407
  210. package/server/service/database/cockroachdb.service.ts +0 -871
  211. package/server/service/database/database.service.ts +0 -776
  212. package/server/service/database/index.ts +0 -7
  213. package/server/service/database/mongodb.service.ts +0 -501
  214. package/server/service/database/mssql.service.ts +0 -932
  215. package/server/service/database/mysql.service.ts +0 -1026
  216. package/server/service/database/oracle.service.ts +0 -1036
  217. package/server/service/database/postgres.service.ts +0 -961
  218. package/server/service/database/sap.service.ts +0 -922
  219. package/server/service/database/sqlite.service.ts +0 -787
  220. package/server/service/session.service.ts +0 -158
  221. package/server/tsconfig.json +0 -20
  222. package/src/adapter/ajax.ts +0 -135
  223. package/src/assets/base.css +0 -1
  224. package/src/assets/database.css +0 -950
  225. package/src/assets/images/collapse.png +0 -0
  226. package/src/assets/images/no-login.png +0 -0
  227. package/src/assets/images/svg/illustrations/illustration-1.svg +0 -1
  228. package/src/assets/images/svg/illustrations/illustration-2.svg +0 -2
  229. package/src/assets/images/svg/illustrations/illustration-3.svg +0 -50
  230. package/src/assets/images/svg/illustrations/illustration-4.svg +0 -1
  231. package/src/assets/images/svg/illustrations/illustration-5.svg +0 -73
  232. package/src/assets/images/svg/illustrations/illustration-6.svg +0 -89
  233. package/src/assets/images/svg/illustrations/illustration-7.svg +0 -39
  234. package/src/assets/images/svg/illustrations/illustration-8.svg +0 -1
  235. package/src/assets/images/svg/separators/curve-2.svg +0 -3
  236. package/src/assets/images/svg/separators/curve.svg +0 -3
  237. package/src/assets/images/svg/separators/line.svg +0 -3
  238. package/src/assets/images/theme/light/screen-1-1000x800.jpg +0 -0
  239. package/src/assets/images/theme/light/screen-2-1000x800.jpg +0 -0
  240. package/src/assets/login/bg.jpg +0 -0
  241. package/src/assets/login/bg.png +0 -0
  242. package/src/assets/login/left.jpg +0 -0
  243. package/src/assets/logo.svg +0 -73
  244. package/src/assets/logo.webp +0 -0
  245. package/src/assets/main.css +0 -1
  246. package/src/base/config.ts +0 -20
  247. package/src/base/detect.ts +0 -134
  248. package/src/base/entity.ts +0 -92
  249. package/src/base/eventBus.ts +0 -37
  250. package/src/components/connection-editor/index.vue +0 -589
  251. package/src/components/dataGrid/index.vue +0 -163
  252. package/src/components/dataGrid/pagination.vue +0 -106
  253. package/src/components/loading/index.vue +0 -43
  254. package/src/components/modal/index.ts +0 -181
  255. package/src/components/modal/index.vue +0 -560
  256. package/src/components/toast/index.ts +0 -44
  257. package/src/components/toast/toast.vue +0 -58
  258. package/src/components/user/name.vue +0 -104
  259. package/src/components/user/selector.vue +0 -416
  260. package/src/domain/SysConfig.ts +0 -74
  261. package/src/platform/App.vue +0 -8
  262. package/src/platform/database/components/connection-detail.vue +0 -1153
  263. package/src/platform/database/components/data-editor.vue +0 -478
  264. package/src/platform/database/components/data-import-export.vue +0 -1602
  265. package/src/platform/database/components/database-detail.vue +0 -1199
  266. package/src/platform/database/components/database-monitor.vue +0 -1086
  267. package/src/platform/database/components/db-tools.vue +0 -1265
  268. package/src/platform/database/components/query-history.vue +0 -1349
  269. package/src/platform/database/components/sql-executor.vue +0 -738
  270. package/src/platform/database/components/sql-query-editor.vue +0 -1046
  271. package/src/platform/database/components/table-data-grid.vue +0 -273
  272. package/src/platform/database/components/table-detail.vue +0 -1173
  273. package/src/platform/database/components/table-editor.vue +0 -917
  274. package/src/platform/database/explorer.vue +0 -1840
  275. package/src/platform/database/index.vue +0 -1193
  276. package/src/platform/database/layout.vue +0 -367
  277. package/src/platform/database/router.ts +0 -37
  278. package/src/platform/database/styles/common.scss +0 -602
  279. package/src/platform/database/types/common.ts +0 -445
  280. package/src/platform/database/utils/export.ts +0 -232
  281. package/src/platform/database/utils/helpers.ts +0 -437
  282. package/src/platform/index.ts +0 -33
  283. package/src/platform/router.ts +0 -41
  284. package/src/platform/vscode/bridge.ts +0 -121
  285. package/src/platform/vscode/components/ConnectionPanel.vue +0 -272
  286. package/src/platform/vscode/components/DatabasePanel.vue +0 -532
  287. package/src/platform/vscode/components/QueryPanel.vue +0 -371
  288. package/src/platform/vscode/entry/connection.ts +0 -13
  289. package/src/platform/vscode/entry/database.ts +0 -13
  290. package/src/platform/vscode/entry/query.ts +0 -13
  291. package/src/platform/vscode/index.ts +0 -5
  292. package/src/service/base.ts +0 -134
  293. package/src/service/database.ts +0 -506
  294. package/src/service/login.ts +0 -121
  295. package/src/shims-vue.d.ts +0 -7
  296. package/src/stores/connection.ts +0 -266
  297. package/src/stores/session.ts +0 -87
  298. package/src/typings/database-types.ts +0 -413
  299. package/src/typings/database.ts +0 -364
  300. package/src/typings/global.d.ts +0 -58
  301. package/src/typings/pinia.d.ts +0 -8
  302. package/src/utils/clipboard.ts +0 -30
  303. package/src/utils/database-types.ts +0 -243
  304. package/src/utils/modal.ts +0 -124
  305. package/src/utils/request.ts +0 -55
  306. package/src/utils/sleep.ts +0 -4
  307. package/src/utils/toast.ts +0 -73
  308. package/src/utils/util.ts +0 -171
  309. package/src/utils/xlsx.ts +0 -228
  310. package/tsconfig.json +0 -33
  311. package/tsconfig.server.json +0 -19
  312. package/vite.config.ts +0 -424
  313. package/vite.config.vscode.ts +0 -47
@@ -1,1153 +0,0 @@
1
- <template>
2
- <div class="connection-detail">
3
- <!-- 连接头部信息 -->
4
- <div class="connection-header">
5
- <div class="connection-info">
6
- <div class="connection-avatar">
7
- <div class="db-logo" :class="getDbLogoClass(connection?.type)">
8
- {{ getDbLogoText(connection?.type) }}
9
- </div>
10
- </div>
11
- <div class="connection-meta">
12
- <h4 class="connection-name">{{ connection?.name }}</h4>
13
- <div class="connection-type-info">
14
- <span class="db-type">{{ getDbTypeLabel(connection?.type) }}</span>
15
- <span class="connection-status" :class="connectionStatusClass">
16
- <div class="status-dot"></div>
17
- {{ connectionStatusText }}
18
- </span>
19
- </div>
20
- </div>
21
- </div>
22
- <div class="connection-actions">
23
- <button class="btn btn-sm btn-outline-info" @click="toggleDetails" title="查看/隐藏详细信息">
24
- <i class="bi" :class="isDetailsExpanded ? 'bi-chevron-up' : 'bi-chevron-down'"></i> 详情
25
- </button>
26
- <button class="btn btn-sm btn-outline-primary" @click="testConnection">
27
- <i class="bi bi-wifi"></i>
28
- </button>
29
- <button class="btn btn-sm btn-outline-secondary" @click="editConnection">
30
- <i class="bi bi-pencil"></i> 编辑
31
- </button>
32
- </div>
33
- </div>
34
-
35
- <!-- 连接详情卡片 -->
36
- <div v-if="isDetailsExpanded" class="connection-details-panel">
37
- <div class="detail-card">
38
- <div class="card-body">
39
- <div class="row">
40
- <!-- 基本信息 -->
41
- <div class="col-md-6">
42
- <h6 class="section-title">
43
- <i class="bi bi-info-circle"></i>
44
- 基本信息
45
- </h6>
46
- <div class="info-grid">
47
- <div class="info-item">
48
- <label class="info-label">主机地址</label>
49
- <div class="info-value">{{ connection?.host }}</div>
50
- </div>
51
- <div class="info-item">
52
- <label class="info-label">端口</label>
53
- <div class="info-value">{{ connection?.port }}</div>
54
- </div>
55
- <div class="info-item">
56
- <label class="info-label">用户名</label>
57
- <div class="info-value">{{ connection?.username }}</div>
58
- </div>
59
- <div class="info-item">
60
- <label class="info-label">数据库类型</label>
61
- <div class="info-value">
62
- <span class="db-type-badge" :class="getDbLogoClass(connection?.type)">
63
- {{ getDbTypeLabel(connection?.type) }}
64
- </span>
65
- </div>
66
- </div>
67
- </div>
68
- </div>
69
-
70
- <!-- 连接统计 -->
71
- <div class="col-md-6">
72
- <h6 class="section-title">
73
- <i class="bi bi-bar-chart"></i>
74
- 连接统计
75
- </h6>
76
- <div class="stats-grid">
77
- <div class="stat-item">
78
- <div class="stat-value">{{ connectionStats.databaseCount || 0 }}</div>
79
- <div class="stat-label">数据库数量</div>
80
- </div>
81
- <div class="stat-item">
82
- <div class="stat-value">{{ connectionStats.tableCount || 0 }}</div>
83
- <div class="stat-label">表总数</div>
84
- </div>
85
- <div class="stat-item">
86
- <div class="stat-value">{{ formatFileSize(connectionStats.totalSize || 0) }}</div>
87
- <div class="stat-label">总大小</div>
88
- </div>
89
- <div class="stat-item">
90
- <div class="stat-value">{{ connectionStats.lastConnected || '从未' }}</div>
91
- <div class="stat-label">最后连接</div>
92
- </div>
93
- </div>
94
- </div>
95
- </div>
96
- </div>
97
- </div>
98
- </div>
99
-
100
- <!-- 快速操作 -->
101
- <div class="quick-actions">
102
- <div class="actions-header">
103
- <h6 class="actions-title">
104
- <i class="bi bi-lightning"></i>
105
- 快速操作
106
- </h6>
107
- </div>
108
- <div class="actions-grid">
109
- <button class="action-btn" @click="showCreateDatabaseModal">
110
- <div class="action-icon">
111
- <i class="bi bi-plus-circle"></i>
112
- </div>
113
- <div class="action-text">创建数据库</div>
114
- </button>
115
- <!-- <button class="action-btn" @click="refreshAll">
116
- <div class="action-icon">
117
- <i class="bi bi-arrow-clockwise"></i>
118
- </div>
119
- <div class="action-text">刷新所有数据库</div>
120
- </button> -->
121
- <!-- <button class="action-btn" @click="activeTab = 'sql'">
122
- <div class="action-icon">
123
- <i class="bi bi-terminal"></i>
124
- </div>
125
- <div class="action-text">SQL查询</div>
126
- </button> -->
127
- <button class="action-btn" @click="exportSchema">
128
- <div class="action-icon">
129
- <i class="bi bi-download"></i>
130
- </div>
131
- <div class="action-text">导出架构</div>
132
- </button>
133
- <button class="action-btn" @click="viewLogs">
134
- <div class="action-icon">
135
- <i class="bi bi-file-text"></i>
136
- </div>
137
- <div class="action-text">查看日志</div>
138
- </button>
139
- </div>
140
- </div>
141
-
142
- <!-- 标签页 -->
143
- <div class="connection-tabs">
144
- <ul class="nav nav-tabs">
145
- <li class="nav-item">
146
- <button
147
- class="nav-link"
148
- :class="{ active: activeTab === 'databases' }"
149
- @click="activeTab = 'databases'"
150
- >
151
- <i class="bi bi-database-fill"></i> 数据库列表
152
- <span class="badge bg-primary ms-1">{{ databases.length }}</span>
153
- </button>
154
- </li>
155
- <li class="nav-item">
156
- <button
157
- class="nav-link"
158
- :class="{ active: activeTab === 'sql' }"
159
- @click="activeTab = 'sql'"
160
- >
161
- <i class="bi bi-terminal"></i> SQL查询
162
- </button>
163
- </li>
164
- </ul>
165
-
166
- <div class="tab-content">
167
- <!-- 数据库列表标签页 -->
168
- <div v-show="activeTab === 'databases'" class="tab-panel">
169
- <div class="databases-section">
170
- <div class="section-header">
171
- <div class="section-actions">
172
- <div class="search-box">
173
- <input
174
- type="text"
175
- class="form-control form-control-sm"
176
- v-model="searchKeyword"
177
- placeholder="搜索数据库..."
178
- style="width: 200px;"
179
- >
180
- </div>
181
- <button class="btn btn-sm btn-outline-primary ms-2" @click="loadDatabases" :disabled="loadingDatabases">
182
- <span v-if="loadingDatabases" class="spinner-border spinner-border-sm me-1"></span>
183
- <i class="bi bi-arrow-clockwise"></i> 刷新
184
- </button>
185
- </div>
186
- </div>
187
-
188
- <div class="databases-list">
189
- <div v-if="loadingDatabases" class="loading-state">
190
- <div class="spinner-border text-primary"></div>
191
- <span>加载数据库列表...</span>
192
- </div>
193
- <div v-else-if="filteredDatabases.length === 0" class="empty-state">
194
- <i class="bi bi-database"></i>
195
- <p>{{ searchKeyword ? '没有找到匹配的数据库' : '暂无数据库' }}</p>
196
- <button class="btn btn-sm btn-primary" @click="showCreateDatabaseModal">
197
- <i class="bi bi-plus"></i> 创建数据库
198
- </button>
199
- </div>
200
- <div v-else class="databases-list-simple">
201
- <div
202
- v-for="database in filteredDatabases"
203
- :key="database.name"
204
- class="database-item"
205
- @click="openDatabase(database)"
206
- >
207
- <div class="database-item-icon">
208
- <i class="bi bi-database"></i>
209
- </div>
210
- <div class="database-item-name">{{ database.name }}</div>
211
- <div class="database-item-actions">
212
- <button class="btn btn-sm btn-outline-secondary" @click.stop="activeTab = 'sql'">
213
- <i class="bi bi-terminal"></i>
214
- </button>
215
- </div>
216
- </div>
217
- </div>
218
- </div>
219
- </div>
220
- </div>
221
-
222
- <!-- SQL查询标签页 -->
223
- <div v-show="activeTab === 'sql'" class="tab-panel">
224
- <div class="sql-section">
225
- <div class="sql-header">
226
- <h6 class="sql-title">
227
- <i class="bi bi-terminal"></i>
228
- SQL查询
229
- </h6>
230
- <div class="sql-db-info" v-if="props.connection">
231
- <span class="badge bg-info">{{ props.connection.name }}</span>
232
- </div>
233
- </div>
234
- <SqlExecutor
235
- :connection="props.connection"
236
- :database="''"
237
- />
238
- </div>
239
- </div>
240
- </div>
241
- </div>
242
-
243
- <!-- 创建数据库模态框 -->
244
- <div v-if="showCreateDatabase" class="modal fade show d-block" style="background: rgba(0,0,0,0.5);">
245
- <div class="modal-dialog">
246
- <div class="modal-content">
247
- <div class="modal-header">
248
- <h5 class="modal-title">创建数据库</h5>
249
- <button type="button" class="btn-close" @click="showCreateDatabase = false"></button>
250
- </div>
251
- <div class="modal-body">
252
- <form>
253
- <div class="mb-3">
254
- <label class="form-label">数据库名称 <span class="text-danger">*</span></label>
255
- <input type="text" class="form-control" v-model="newDatabase.name" placeholder="输入数据库名称" required>
256
- </div>
257
-
258
- <!-- MySQL特定选项 -->
259
- <div v-if="connection?.type === 'mysql'">
260
- <div class="mb-3">
261
- <label class="form-label">字符集</label>
262
- <select class="form-select" v-model="newDatabase.options.charset">
263
- <option value="">默认</option>
264
- <option value="utf8mb4">utf8mb4</option>
265
- <option value="utf8">utf8</option>
266
- <option value="latin1">latin1</option>
267
- </select>
268
- </div>
269
- <div class="mb-3">
270
- <label class="form-label">排序规则</label>
271
- <select class="form-select" v-model="newDatabase.options.collation">
272
- <option value="">默认</option>
273
- <option value="utf8mb4_unicode_ci">utf8mb4_unicode_ci</option>
274
- <option value="utf8mb4_general_ci">utf8mb4_general_ci</option>
275
- <option value="utf8_unicode_ci">utf8_unicode_ci</option>
276
- </select>
277
- </div>
278
- </div>
279
-
280
- <!-- PostgreSQL特定选项 -->
281
- <div v-if="connection?.type === 'postgres'">
282
- <div class="mb-3">
283
- <label class="form-label">所有者</label>
284
- <input type="text" class="form-control" v-model="newDatabase.options.owner" placeholder="数据库所有者">
285
- </div>
286
- <div class="mb-3">
287
- <label class="form-label">模板</label>
288
- <input type="text" class="form-control" v-model="newDatabase.options.template" placeholder="模板数据库">
289
- </div>
290
- <div class="mb-3">
291
- <label class="form-label">编码</label>
292
- <select class="form-select" v-model="newDatabase.options.encoding">
293
- <option value="">默认</option>
294
- <option value="UTF8">UTF8</option>
295
- <option value="LATIN1">LATIN1</option>
296
- </select>
297
- </div>
298
- <div class="mb-3">
299
- <label class="form-label">表空间</label>
300
- <input type="text" class="form-control" v-model="newDatabase.options.tablespace" placeholder="表空间">
301
- </div>
302
- </div>
303
-
304
- <!-- SQL Server特定选项 -->
305
- <div v-if="connection?.type === 'mssql'">
306
- <div class="mb-3">
307
- <label class="form-label">排序规则</label>
308
- <input type="text" class="form-control" v-model="newDatabase.options.collation" placeholder="排序规则">
309
- </div>
310
- </div>
311
- </form>
312
- </div>
313
- <div class="modal-footer">
314
- <button type="button" class="btn btn-secondary" @click="showCreateDatabase = false">取消</button>
315
- <button type="button" class="btn btn-primary" @click="createDatabase" :disabled="!newDatabase.name || creatingDatabase">
316
- <span v-if="creatingDatabase" class="spinner-border spinner-border-sm me-2"></span>
317
- 创建
318
- </button>
319
- </div>
320
- </div>
321
- </div>
322
- </div>
323
- </div>
324
- </template>
325
-
326
- <script lang="ts" setup>
327
- import { ref, computed, onMounted, watch } from 'vue';
328
- import { useRouter } from 'vue-router';
329
- import type { ConnectionEntity } from '@/typings/database';
330
- import { useConnectionStore } from '@/stores/connection';
331
- import SqlExecutor from './sql-executor.vue';
332
- import { modal } from '@/utils/modal';
333
-
334
- const router = useRouter();
335
-
336
- const props = defineProps<{
337
- connection: ConnectionEntity | null;
338
- }>();
339
-
340
- const emit = defineEmits<{
341
- 'test-connection': [connection: ConnectionEntity];
342
- 'edit-connection': [connection: ConnectionEntity];
343
- 'refresh-all': [connection: ConnectionEntity];
344
- 'open-sql-query': [connection: ConnectionEntity];
345
- 'export-schema': [connection: ConnectionEntity];
346
- 'view-logs': [connection: ConnectionEntity];
347
- 'create-database': [];
348
- 'open-database': [connection: ConnectionEntity, database: string];
349
- }>();
350
-
351
- // 初始化连接 store
352
- const connectionStore = useConnectionStore();
353
-
354
- // 连接统计信息
355
- const connectionStats = ref({
356
- databaseCount: 0,
357
- tableCount: 0,
358
- totalSize: 0,
359
- lastConnected: null as string | null
360
- });
361
-
362
- // 连接状态: 'unknown' | 'connected' | 'disconnected' | 'testing'
363
- const connectionStatus = ref<'unknown' | 'connected' | 'disconnected' | 'testing'>('unknown');
364
-
365
- // 搜索关键字
366
- const searchKeyword = ref('');
367
-
368
- // 折叠状态
369
- const isDetailsExpanded = ref(false);
370
-
371
- // 切换折叠状态
372
- function toggleDetails() {
373
- isDetailsExpanded.value = !isDetailsExpanded.value;
374
- }
375
-
376
- // 创建数据库相关
377
- const showCreateDatabase = ref(false);
378
- const creatingDatabase = ref(false);
379
- const newDatabase = ref({
380
- name: '',
381
- options: {
382
- charset: '',
383
- collation: '',
384
- owner: '',
385
- template: '',
386
- encoding: '',
387
- tablespace: ''
388
- }
389
- });
390
-
391
- // 标签页状态
392
- const activeTab = ref('databases');
393
-
394
- // 监听连接变化
395
- watch(() => props.connection, (newConnection) => {
396
- connectionStore.setCurrentConnection(newConnection);
397
- if (newConnection) {
398
- loadConnectionStats();
399
- // 重置连接状态为未知
400
- connectionStatus.value = 'unknown';
401
- // 自动测试连接
402
- testConnection();
403
- }
404
- }, { immediate: true });
405
-
406
- // 生命周期
407
- onMounted(() => {
408
- if (props.connection) {
409
- loadConnectionStats();
410
- }
411
- });
412
-
413
- // 数据库列表(从 store 获取)
414
- const databases = computed(() => connectionStore.databases);
415
- const loadingDatabases = computed(() => connectionStore.isLoadingDatabases);
416
-
417
- // 连接状态的显示类和文本
418
- const connectionStatusClass = computed(() => {
419
- switch (connectionStatus.value) {
420
- case 'connected':
421
- return 'status-online';
422
- case 'disconnected':
423
- return 'status-offline';
424
- case 'testing':
425
- return 'status-testing';
426
- default:
427
- return 'status-offline';
428
- }
429
- });
430
-
431
- const connectionStatusText = computed(() => {
432
- switch (connectionStatus.value) {
433
- case 'connected':
434
- return '已连接';
435
- case 'disconnected':
436
- return '未连接';
437
- case 'testing':
438
- return '测试中...';
439
- default:
440
- return '未知';
441
- }
442
- });
443
-
444
- // 方法
445
- function loadConnectionStats() {
446
- // 模拟加载连接统计信息
447
- connectionStats.value = {
448
- databaseCount: connectionStore.databaseCount,
449
- tableCount: connectionStore.tableCount,
450
- totalSize: 1024 * 1024 * 512, // 512MB
451
- lastConnected: '2小时前'
452
- };
453
- }
454
-
455
- function loadDatabases() {
456
- connectionStore.loadDatabases();
457
- }
458
-
459
- const filteredDatabases = computed(() => {
460
- if (!searchKeyword.value) {
461
- return databases.value;
462
- }
463
- const keyword = searchKeyword.value.toLowerCase();
464
- return databases.value.filter(db =>
465
- db.name.toLowerCase().includes(keyword)
466
- );
467
- });
468
-
469
- function openDatabase(database: any) {
470
- if (props.connection) {
471
- emit('open-database', props.connection, database.name);
472
- router.push({
473
- path: `/database/explorer`,
474
- query: { connectionId: props.connection.id, database: database.name }
475
- });
476
- }
477
- }
478
-
479
- async function testConnection() {
480
- if (!props.connection) return;
481
-
482
- connectionStatus.value = 'testing';
483
-
484
- try {
485
- const isConnected = await connectionStore.testConnection(props.connection);
486
- connectionStatus.value = isConnected ? 'connected' : 'disconnected';
487
- } catch (error) {
488
- console.error('连接测试失败:', error);
489
- connectionStatus.value = 'disconnected';
490
- }
491
- }
492
-
493
- function editConnection() {
494
- if (props.connection) {
495
- emit('edit-connection', props.connection);
496
- }
497
- }
498
-
499
- function refreshAll() {
500
- if (props.connection) {
501
- emit('refresh-all', props.connection);
502
- }
503
- }
504
-
505
- function exportSchema() {
506
- if (props.connection) {
507
- emit('export-schema', props.connection);
508
- }
509
- }
510
-
511
- function viewLogs() {
512
- if (props.connection) {
513
- emit('view-logs', props.connection);
514
- }
515
- }
516
-
517
- function showCreateDatabaseModal() {
518
- emit('create-database');
519
- showCreateDatabase.value = true;
520
- }
521
-
522
- async function createDatabase() {
523
- if (!newDatabase.value.name) {
524
- modal.warning('请输入数据库名称');
525
- return;
526
- }
527
-
528
- if (props.connection) {
529
- creatingDatabase.value = true;
530
- try {
531
- await connectionStore.createDatabase(newDatabase.value.name);
532
- modal.success('数据库创建成功');
533
- showCreateDatabase.value = false;
534
- // 重置表单
535
- newDatabase.value = {
536
- name: '',
537
- options: {
538
- charset: '',
539
- collation: '',
540
- owner: '',
541
- template: '',
542
- encoding: '',
543
- tablespace: ''
544
- }
545
- };
546
- // 刷新数据库列表
547
- await loadDatabases();
548
- // 通知父组件刷新数据库缓存
549
- emit('create-database');
550
- } catch (error: any) {
551
- modal.error(error.message || '创建数据库失败');
552
- } finally {
553
- creatingDatabase.value = false;
554
- }
555
- }
556
- }
557
-
558
- // 格式化文件大小
559
- function formatFileSize(bytes: number): string {
560
- if (bytes === 0) return '0 B';
561
- const k = 1024;
562
- const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
563
- const i = Math.floor(Math.log(bytes) / Math.log(k));
564
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
565
- }
566
-
567
- // 格式化日期时间
568
- function formatDate(dateString: string): string {
569
- if (!dateString) return '';
570
- const date = new Date(dateString);
571
- return date.toLocaleString();
572
- }
573
-
574
- // 获取数据库类型标签
575
- function getDbTypeLabel(type?: string): string {
576
- const typeMap: Record<string, string> = {
577
- mysql: 'MySQL',
578
- postgres: 'PostgreSQL',
579
- mssql: 'SQL Server',
580
- sqlite: 'SQLite',
581
- oracle: 'Oracle'
582
- };
583
- return typeMap[type || ''] || 'Unknown';
584
- }
585
-
586
- // 获取数据库Logo类名
587
- function getDbLogoClass(type?: string): string {
588
- return `db-${type || ''}`;
589
- }
590
-
591
- // 获取数据库Logo文本
592
- function getDbLogoText(type?: string): string {
593
- const textMap: Record<string, string> = {
594
- mysql: 'MY',
595
- postgres: 'PG',
596
- mssql: 'MS',
597
- sqlite: 'SQ',
598
- oracle: 'OR'
599
- };
600
- return textMap[type || ''] || 'DB';
601
- }
602
- </script>
603
-
604
- <style scoped>
605
- .connection-detail {
606
- padding: 20px;
607
- display: flex;
608
- flex-direction: column;
609
- height: 100%;
610
- gap: 20px;
611
- }
612
-
613
- .connection-header {
614
- display: flex;
615
- justify-content: space-between;
616
- align-items: center;
617
- margin-bottom: 20px;
618
- padding: 20px;
619
- background-color: #f8f9fa;
620
- border-radius: 8px;
621
- }
622
-
623
- .connection-info {
624
- display: flex;
625
- align-items: center;
626
- gap: 16px;
627
- }
628
-
629
- .connection-avatar {
630
- width: 60px;
631
- height: 60px;
632
- display: flex;
633
- align-items: center;
634
- justify-content: center;
635
- border-radius: 8px;
636
- background-color: #e9ecef;
637
- }
638
-
639
- .db-logo {
640
- font-size: 24px;
641
- font-weight: bold;
642
- color: #6c757d;
643
- }
644
-
645
- .db-mysql {
646
- background-color: #4CAF50;
647
- color: white;
648
- }
649
-
650
- .db-postgres {
651
- background-color: #336791;
652
- color: white;
653
- }
654
-
655
- .db-mssql {
656
- background-color: #0078d4;
657
- color: white;
658
- }
659
-
660
- .db-sqlite {
661
- background-color: #003B57;
662
- color: white;
663
- }
664
-
665
- .db-oracle {
666
- background-color: #F80000;
667
- color: white;
668
- }
669
-
670
- .connection-meta {
671
- display: flex;
672
- flex-direction: column;
673
- gap: 4px;
674
- }
675
-
676
- .connection-name {
677
- margin: 0;
678
- font-size: 20px;
679
- font-weight: 600;
680
- }
681
-
682
- .connection-type-info {
683
- display: flex;
684
- align-items: center;
685
- gap: 12px;
686
- }
687
-
688
- .db-type {
689
- padding: 4px 12px;
690
- border-radius: 12px;
691
- background-color: #e9ecef;
692
- font-size: 12px;
693
- font-weight: 500;
694
- }
695
-
696
- .connection-status {
697
- display: flex;
698
- align-items: center;
699
- gap: 6px;
700
- font-size: 14px;
701
- }
702
-
703
- .status-dot {
704
- width: 8px;
705
- height: 8px;
706
- border-radius: 50%;
707
- background-color: #6c757d;
708
- }
709
-
710
- .status-online .status-dot {
711
- background-color: #28a745;
712
- }
713
-
714
- .status-offline .status-dot {
715
- background-color: #dc3545;
716
- }
717
-
718
- .status-testing .status-dot {
719
- background-color: #ffc107;
720
- animation: pulse 1s infinite;
721
- }
722
-
723
- @keyframes pulse {
724
- 0%, 100% {
725
- opacity: 1;
726
- }
727
- 50% {
728
- opacity: 0.5;
729
- }
730
- }
731
-
732
- .connection-actions {
733
- display: flex;
734
- gap: 8px;
735
- }
736
-
737
- .connection-details-panel {
738
- margin-bottom: 30px;
739
- animation: fadeIn 0.3s ease;
740
- }
741
-
742
- .section-title {
743
- margin: 0 0 16px 0;
744
- font-size: 16px;
745
- font-weight: 600;
746
- display: flex;
747
- align-items: center;
748
- gap: 8px;
749
- color: #343a40;
750
- padding-bottom: 8px;
751
- border-bottom: 1px solid #e9ecef;
752
- }
753
-
754
- @keyframes fadeIn {
755
- from {
756
- opacity: 0;
757
- transform: translateY(-10px);
758
- }
759
- to {
760
- opacity: 1;
761
- transform: translateY(0);
762
- }
763
- }
764
-
765
- .detail-card {
766
- border: 1px solid #dee2e6;
767
- border-radius: 8px;
768
- overflow: hidden;
769
- }
770
-
771
- .card-header {
772
- padding: 16px;
773
- background-color: #f8f9fa;
774
- border-bottom: 1px solid #dee2e6;
775
- }
776
-
777
- .card-title {
778
- margin: 0;
779
- font-size: 16px;
780
- font-weight: 600;
781
- display: flex;
782
- align-items: center;
783
- gap: 8px;
784
- }
785
-
786
- .card-body {
787
- padding: 16px;
788
- }
789
-
790
- .info-grid {
791
- display: grid;
792
- grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
793
- gap: 16px;
794
- margin-bottom: 10px;
795
- }
796
-
797
- .info-item {
798
- display: flex;
799
- flex-direction: column;
800
- gap: 4px;
801
- padding: 10px;
802
- background-color: #f8f9fa;
803
- border-radius: 6px;
804
- transition: all 0.2s ease;
805
- }
806
-
807
- .info-item:hover {
808
- background-color: #e9ecef;
809
- transform: translateY(-1px);
810
- }
811
-
812
- .info-label {
813
- font-size: 12px;
814
- font-weight: 500;
815
- color: #6c757d;
816
- text-transform: uppercase;
817
- letter-spacing: 0.5px;
818
- }
819
-
820
- .info-value {
821
- font-size: 14px;
822
- font-weight: 500;
823
- color: #343a40;
824
- }
825
-
826
- .db-type-badge {
827
- padding: 4px 10px;
828
- border-radius: 12px;
829
- font-size: 12px;
830
- font-weight: 500;
831
- }
832
-
833
- .stats-grid {
834
- display: grid;
835
- grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
836
- gap: 16px;
837
- }
838
-
839
- .stat-item {
840
- text-align: center;
841
- padding: 12px;
842
- background-color: #f8f9fa;
843
- border-radius: 6px;
844
- transition: all 0.2s ease;
845
- }
846
-
847
- .stat-item:hover {
848
- background-color: #e9ecef;
849
- transform: translateY(-1px);
850
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
851
- }
852
-
853
- .stat-value {
854
- font-size: 20px;
855
- font-weight: 600;
856
- color: #343a40;
857
- }
858
-
859
- .stat-label {
860
- font-size: 12px;
861
- color: #6c757d;
862
- margin-top: 4px;
863
- }
864
-
865
- .quick-actions {
866
- margin-bottom: 30px;
867
- padding: 20px;
868
- background-color: #f8f9fa;
869
- border-radius: 8px;
870
- }
871
-
872
- .actions-header {
873
- margin-bottom: 16px;
874
- }
875
-
876
- .actions-title {
877
- margin: 0;
878
- font-size: 16px;
879
- font-weight: 600;
880
- display: flex;
881
- align-items: center;
882
- gap: 8px;
883
- }
884
-
885
- .actions-grid {
886
- display: grid;
887
- grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
888
- gap: 16px;
889
- }
890
-
891
- .action-btn {
892
- display: flex;
893
- flex-direction: column;
894
- align-items: center;
895
- gap: 8px;
896
- padding: 16px;
897
- background-color: white;
898
- border: 1px solid #dee2e6;
899
- border-radius: 8px;
900
- cursor: pointer;
901
- transition: all 0.2s ease;
902
- }
903
-
904
- .action-btn:hover {
905
- background-color: #e9ecef;
906
- transform: translateY(-2px);
907
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
908
- }
909
-
910
- .action-icon {
911
- font-size: 24px;
912
- color: #6c757d;
913
- }
914
-
915
- .action-text {
916
- font-size: 14px;
917
- font-weight: 500;
918
- color: #343a40;
919
- }
920
-
921
- .connection-tabs {
922
- border: 1px solid #dee2e6;
923
- border-radius: 8px;
924
- flex: 1;
925
- display: flex;
926
- flex-direction: column;
927
- }
928
-
929
- .nav-tabs {
930
- border-bottom: 1px solid #dee2e6;
931
- background-color: #f8f9fa;
932
- }
933
-
934
- .nav-link {
935
- border: none;
936
- border-radius: 0;
937
- padding: 12px 20px;
938
- font-size: 14px;
939
- font-weight: 500;
940
- transition: all 0.2s ease;
941
- }
942
-
943
- .nav-link:hover {
944
- background-color: #e9ecef;
945
- }
946
-
947
- .nav-link.active {
948
- background-color: white;
949
- border-bottom: 2px solid #0d6efd;
950
- }
951
-
952
- .tab-content {
953
- flex: 1;
954
- display: flex;
955
- flex-direction: column;
956
- overflow: hidden;
957
- }
958
-
959
- .tab-panel {
960
- padding: 20px;
961
- flex: 1;
962
- display: flex;
963
- flex-direction: column;
964
- overflow: hidden;
965
- }
966
-
967
- .databases-section {
968
- display: flex;
969
- flex-direction: column;
970
- gap: 16px;
971
- flex: 1;
972
- overflow: hidden;
973
- }
974
-
975
- .section-header {
976
- display: flex;
977
- justify-content: flex-end;
978
- align-items: center;
979
- }
980
-
981
- .section-actions {
982
- display: flex;
983
- align-items: center;
984
- gap: 8px;
985
- }
986
-
987
- .databases-list {
988
- min-height: 300px;
989
- height: 100%;
990
- overflow-y: auto;
991
- padding-right: 8px;
992
- }
993
-
994
- .loading-state {
995
- display: flex;
996
- flex-direction: column;
997
- align-items: center;
998
- justify-content: center;
999
- padding: 60px 20px;
1000
- gap: 16px;
1001
- }
1002
-
1003
- .empty-state {
1004
- display: flex;
1005
- flex-direction: column;
1006
- align-items: center;
1007
- justify-content: center;
1008
- padding: 60px 20px;
1009
- gap: 16px;
1010
- text-align: center;
1011
- }
1012
-
1013
- .empty-state i {
1014
- font-size: 48px;
1015
- color: #ced4da;
1016
- }
1017
-
1018
- .empty-state p {
1019
- margin: 0;
1020
- color: #6c757d;
1021
- font-size: 16px;
1022
- }
1023
-
1024
- .databases-list-simple {
1025
- display: grid;
1026
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1027
- gap: 12px;
1028
- }
1029
-
1030
- .database-item {
1031
- display: flex;
1032
- flex-direction: column;
1033
- align-items: center;
1034
- gap: 8px;
1035
- padding: 16px;
1036
- border: 1px solid #dee2e6;
1037
- border-radius: 6px;
1038
- cursor: pointer;
1039
- transition: all 0.2s ease;
1040
- text-align: center;
1041
- min-height: 100px;
1042
- }
1043
-
1044
- .database-item:hover {
1045
- border-color: #0d6efd;
1046
- background-color: #f8f9fa;
1047
- transform: translateY(-2px);
1048
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
1049
- }
1050
-
1051
- .database-item-icon {
1052
- font-size: 32px;
1053
- color: #6c757d;
1054
- }
1055
-
1056
- .database-item-name {
1057
- font-size: 14px;
1058
- font-weight: 500;
1059
- color: #343a40;
1060
- overflow: hidden;
1061
- text-overflow: ellipsis;
1062
- white-space: nowrap;
1063
- max-width: 100%;
1064
- }
1065
-
1066
- .database-item-actions {
1067
- display: flex;
1068
- gap: 4px;
1069
- margin-top: auto;
1070
- }
1071
-
1072
- .sql-section {
1073
- display: flex;
1074
- flex-direction: column;
1075
- gap: 16px;
1076
- flex: 1;
1077
- overflow: hidden;
1078
- }
1079
-
1080
- .sql-header {
1081
- display: flex;
1082
- justify-content: space-between;
1083
- align-items: center;
1084
- }
1085
-
1086
- .sql-title {
1087
- margin: 0;
1088
- font-size: 16px;
1089
- font-weight: 600;
1090
- display: flex;
1091
- align-items: center;
1092
- gap: 8px;
1093
- }
1094
-
1095
- .sql-db-info {
1096
- display: flex;
1097
- align-items: center;
1098
- gap: 8px;
1099
- }
1100
-
1101
- /* 响应式设计 */
1102
- @media (max-width: 768px) {
1103
- .connection-header {
1104
- flex-direction: column;
1105
- align-items: flex-start;
1106
- gap: 16px;
1107
- }
1108
-
1109
- .connection-actions {
1110
- align-self: flex-end;
1111
- }
1112
-
1113
- .connection-cards {
1114
- grid-template-columns: 1fr;
1115
- }
1116
-
1117
- .info-grid {
1118
- grid-template-columns: 1fr;
1119
- }
1120
-
1121
- .stats-grid {
1122
- grid-template-columns: repeat(2, 1fr);
1123
- }
1124
-
1125
- .actions-grid {
1126
- grid-template-columns: repeat(2, 1fr);
1127
- }
1128
-
1129
- .databases-list-simple {
1130
- grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
1131
- gap: 10px;
1132
- }
1133
-
1134
- .database-item {
1135
- padding: 12px;
1136
- min-height: 80px;
1137
- }
1138
-
1139
- .database-item-icon {
1140
- font-size: 24px;
1141
- }
1142
-
1143
- .database-item-name {
1144
- font-size: 12px;
1145
- }
1146
-
1147
- .nav-link {
1148
- padding: 10px 16px;
1149
- font-size: 13px;
1150
- }
1151
- }
1152
- </style>
1153
-